home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / C++ / Direct3D / HDRLighting / HDRLighting.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-09-28  |  109.5 KB  |  2,942 lines

  1. //-----------------------------------------------------------------------------
  2. // File: HDRLighting.cpp
  3. //
  4. // Desc: This sample demonstrates some high dynamic range lighting effects 
  5. //       using floating point textures.
  6. //
  7. // The algorithms described in this sample are based very closely on the 
  8. // lighting effects implemented in Masaki Kawase's Rthdribl sample and the tone 
  9. // mapping process described in the whitepaper "Tone Reproduction for Digital 
  10. // Images"
  11. //
  12. // Real-Time High Dynamic Range Image-Based Lighting (Rthdribl)
  13. // Masaki Kawase
  14. // http://www.daionet.gr.jp/~masa/rthdribl/ 
  15. //
  16. // "Photographic Tone Reproduction for Digital Images"
  17. // Erik Reinhard, Mike Stark, Peter Shirley and Jim Ferwerda
  18. // http://www.cs.utah.edu/~reinhard/cdrom/ 
  19. //
  20. // Copyright (c) Microsoft Corporation. All rights reserved.
  21. //-----------------------------------------------------------------------------
  22. #include "dxstdafx.h"
  23. #include "glaredefd3d.h"
  24. #include <stdio.h>
  25. #include "resource.h"
  26.  
  27. //#define DEBUG_VS   // Uncomment this line to debug vertex shaders 
  28. //#define DEBUG_PS   // Uncomment this line to debug pixel shaders 
  29.  
  30.  
  31.  
  32. //-----------------------------------------------------------------------------
  33. // Constants and custom types
  34. //-----------------------------------------------------------------------------
  35. #define MAX_SAMPLES           16      // Maximum number of texture grabs
  36.  
  37. #define NUM_LIGHTS            2       // Number of lights in the scene
  38.  
  39. #define EMISSIVE_COEFFICIENT  39.78f  // Emissive color multiplier for each lumen
  40.                                       // of light intensity                                    
  41. #define NUM_TONEMAP_TEXTURES  4       // Number of stages in the 4x4 down-scaling 
  42.                                       // of average luminance textures
  43. #define NUM_STAR_TEXTURES     12      // Number of textures used for the star
  44.                                       // post-processing effect
  45. #define NUM_BLOOM_TEXTURES    3       // Number of textures used for the bloom
  46.                                       // post-processing effect
  47.                                     
  48.  
  49. // Texture coordinate rectangle
  50. struct CoordRect
  51. {
  52.     float fLeftU, fTopV;
  53.     float fRightU, fBottomV;
  54. };
  55.  
  56.  
  57. // World vertex format
  58. struct WorldVertex
  59. {
  60.     D3DXVECTOR3 p; // position
  61.     D3DXVECTOR3 n; // normal
  62.     D3DXVECTOR2 t; // texture coordinate
  63.  
  64.     static const DWORD FVF;
  65. };
  66. const DWORD WorldVertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;
  67.  
  68.  
  69. // Screen quad vertex format
  70. struct ScreenVertex
  71. {
  72.     D3DXVECTOR4 p; // position
  73.     D3DXVECTOR2 t; // texture coordinate
  74.  
  75.     static const DWORD FVF;
  76. };
  77. const DWORD ScreenVertex::FVF = D3DFVF_XYZRHW | D3DFVF_TEX1;
  78.  
  79.  
  80.  
  81. //--------------------------------------------------------------------------------------
  82. // Global variables
  83. //--------------------------------------------------------------------------------------
  84. IDirect3DDevice9*       g_pd3dDevice = NULL;    // D3D Device object
  85. ID3DXFont*              g_pFont = NULL;         // Font for drawing text
  86. ID3DXSprite*            g_pTextSprite = NULL;   // Sprite for batching draw text calls
  87. ID3DXEffect*            g_pEffect = NULL;       // D3DX effect interface
  88. CFirstPersonCamera      g_Camera;               // A model viewing camera
  89. D3DFORMAT               g_LuminanceFormat;      // Format to use for luminance map
  90. bool                    g_bShowHelp = true;     // If true, it renders the UI control text
  91. CDXUTDialog             g_HUD;                  // dialog for standard controls
  92. CDXUTDialog             g_SampleUI;             // dialog for sample specific controls
  93.  
  94. PDIRECT3DTEXTURE9 g_pTexScene = NULL;            // HDR render target containing the scene
  95. PDIRECT3DTEXTURE9 g_pTexSceneScaled = NULL;      // Scaled copy of the HDR scene
  96. PDIRECT3DTEXTURE9 g_pTexBrightPass = NULL;       // Bright-pass filtered copy of the scene
  97. PDIRECT3DTEXTURE9 g_pTexAdaptedLuminanceCur = NULL;  // The luminance that the user is currenly adapted to
  98. PDIRECT3DTEXTURE9 g_pTexAdaptedLuminanceLast = NULL; // The luminance that the user is currenly adapted to
  99. PDIRECT3DTEXTURE9 g_pTexStarSource = NULL;       // Star effect source texture
  100. PDIRECT3DTEXTURE9 g_pTexBloomSource = NULL;      // Bloom effect source texture
  101.  
  102. PDIRECT3DTEXTURE9 g_pTexWall = NULL;     // Stone texture for the room walls
  103. PDIRECT3DTEXTURE9 g_pTexFloor = NULL;    // Concrete texture for the room floor
  104. PDIRECT3DTEXTURE9 g_pTexCeiling = NULL;  // Plaster texture for the room ceiling
  105. PDIRECT3DTEXTURE9 g_pTexPainting = NULL; // Texture for the paintings on the wall
  106.  
  107.  
  108. PDIRECT3DTEXTURE9 g_apTexBloom[NUM_BLOOM_TEXTURES] = {0};     // Blooming effect working textures
  109. PDIRECT3DTEXTURE9 g_apTexStar[NUM_STAR_TEXTURES] = {0};       // Star effect working textures
  110. PDIRECT3DTEXTURE9 g_apTexToneMap[NUM_TONEMAP_TEXTURES] = {0}; // Log average luminance samples 
  111.                                                         // from the HDR render target
  112.  
  113. LPD3DXMESH        g_pWorldMesh = NULL;       // Mesh to contain world objects
  114. LPD3DXMESH        g_pmeshSphere = NULL;      // Representation of point light
  115.  
  116. CGlareDef         g_GlareDef;         // Glare defintion
  117. EGLARELIBTYPE     g_eGlareType;       // Enumerated glare type
  118.  
  119. D3DXVECTOR4       g_avLightPosition[NUM_LIGHTS];    // Light positions in world space
  120. D3DXVECTOR4       g_avLightIntensity[NUM_LIGHTS];   // Light floating point intensities
  121. int               g_nLightLogIntensity[NUM_LIGHTS]; // Light intensities on a log scale
  122. int               g_nLightMantissa[NUM_LIGHTS];     // Mantissa of the light intensity
  123.  
  124. DWORD g_dwCropWidth;    // Width of the cropped scene texture
  125. DWORD g_dwCropHeight;   // Height of the cropped scene texture
  126.  
  127. float       g_fKeyValue;              // Middle gray key value for tone mapping
  128.  
  129. bool        g_bToneMap;               // True when scene is to be tone mapped            
  130. bool        g_bDetailedStats;         // True when state variables should be rendered
  131. bool        g_bDrawHelp;              // True when help instructions are to be drawn
  132. bool        g_bBlueShift;             // True when blue shift is to be factored in
  133. bool        g_bAdaptationInvalid;     // True when adaptation level needs refreshing
  134.  
  135.  
  136. //--------------------------------------------------------------------------------------
  137. // UI control IDs
  138. //--------------------------------------------------------------------------------------
  139. #define IDC_STATIC              -1
  140. #define IDC_TOGGLEFULLSCREEN    1
  141. #define IDC_TOGGLEREF           3
  142. #define IDC_CHANGEDEVICE        4
  143. #define IDC_GLARETYPE           5
  144. #define IDC_LIGHT0_LABEL        6
  145. #define IDC_LIGHT1_LABEL        7
  146. #define IDC_LIGHT0              8
  147. #define IDC_LIGHT1              9
  148. #define IDC_KEYVALUE            10
  149. #define IDC_KEYVALUE_LABEL      11
  150. #define IDC_TONEMAP             12
  151. #define IDC_BLUESHIFT           13
  152. #define IDC_RESET               14
  153.  
  154.  
  155. //--------------------------------------------------------------------------------------
  156. // Forward declarations 
  157. //--------------------------------------------------------------------------------------
  158. bool    CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed );
  159. void    CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps );
  160. HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  161. HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  162. void    CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime );
  163. void    CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime );
  164. LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing );
  165. void    CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown  );
  166. void    CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl );
  167. void    CALLBACK OnLostDevice();
  168. void    CALLBACK OnDestroyDevice();
  169.  
  170. void    InitApp();
  171. HRESULT LoadMesh( IDirect3DDevice9* pd3dDevice, WCHAR* strFileName, ID3DXMesh** ppMesh );
  172. void    RenderText();
  173.  
  174. // Scene geometry initialization routines
  175. void    SetTextureCoords( WorldVertex* pVertex, float u, float v );
  176. HRESULT BuildWorldMesh();
  177. HRESULT BuildColumn( WorldVertex* &pV, float x, float y, float z, float width );
  178.  
  179.  
  180. // Post-processing source textures creation
  181. HRESULT Scene_To_SceneScaled();
  182. HRESULT SceneScaled_To_BrightPass();
  183. HRESULT BrightPass_To_StarSource();
  184. HRESULT StarSource_To_BloomSource();
  185.  
  186.  
  187. // Post-processing helper functions
  188. HRESULT GetTextureRect( PDIRECT3DTEXTURE9 pTexture, RECT* pRect );
  189. HRESULT GetTextureCoords( PDIRECT3DTEXTURE9 pTexSrc, RECT* pRectSrc, PDIRECT3DTEXTURE9 pTexDest, RECT* pRectDest, CoordRect* pCoords );
  190.  
  191.  
  192. // Sample offset calculation. These offsets are passed to corresponding
  193. // pixel shaders.
  194. HRESULT GetSampleOffsets_GaussBlur5x5(DWORD dwD3DTexWidth, DWORD dwD3DTexHeight, D3DXVECTOR2* avTexCoordOffset, D3DXVECTOR4* avSampleWeights, FLOAT fMultiplier = 1.0f );
  195. HRESULT GetSampleOffsets_Bloom(DWORD dwD3DTexSize, float afTexCoordOffset[15], D3DXVECTOR4* avColorWeight, float fDeviation, FLOAT fMultiplier=1.0f);    
  196. HRESULT GetSampleOffsets_Star(DWORD dwD3DTexSize, float afTexCoordOffset[15], D3DXVECTOR4* avColorWeight, float fDeviation);    
  197. HRESULT GetSampleOffsets_DownScale4x4( DWORD dwWidth, DWORD dwHeight, D3DXVECTOR2 avSampleOffsets[] );
  198. HRESULT GetSampleOffsets_DownScale2x2( DWORD dwWidth, DWORD dwHeight, D3DXVECTOR2 avSampleOffsets[] );
  199.  
  200.  
  201. // Tone mapping and post-process lighting effects
  202. HRESULT MeasureLuminance();
  203. HRESULT CalculateAdaptation();
  204. HRESULT RenderStar();
  205. HRESULT RenderBloom();
  206.  
  207.  
  208. // Methods to control scene lights
  209. HRESULT AdjustLight(UINT iLight, bool bIncrement); 
  210. HRESULT RefreshLights();
  211.  
  212. HRESULT RenderScene();
  213. void    RenderText();
  214. HRESULT ClearTexture( LPDIRECT3DTEXTURE9 pTexture );
  215.  
  216. VOID    ResetOptions();
  217. VOID    DrawFullScreenQuad(float fLeftU, float fTopV, float fRightU, float fBottomV);
  218. VOID    DrawFullScreenQuad(CoordRect c) { DrawFullScreenQuad( c.fLeftU, c.fTopV, c.fRightU, c.fBottomV ); }
  219.  
  220. LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  221.  
  222. static inline float GaussianDistribution( float x, float y, float rho );
  223.  
  224.  
  225.  
  226.  
  227. //--------------------------------------------------------------------------------------
  228. // Entry point to the program. Initializes everything and goes into a message processing 
  229. // loop. Idle time is used to render the scene.
  230. //--------------------------------------------------------------------------------------
  231. INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
  232. {
  233.     // Set the callback functions. These functions allow the sample framework to notify
  234.     // the application about device changes, user input, and windows messages.  The 
  235.     // callbacks are optional so you need only set callbacks for events you're interested 
  236.     // in. However, if you don't handle the device reset/lost callbacks then the sample 
  237.     // framework won't be able to reset your device since the application must first 
  238.     // release all device resources before resetting.  Likewise, if you don't handle the 
  239.     // device created/destroyed callbacks then the sample framework won't be able to 
  240.     // recreate your device resources.
  241.     DXUTSetCallbackDeviceCreated( OnCreateDevice );
  242.     DXUTSetCallbackDeviceReset( OnResetDevice );
  243.     DXUTSetCallbackDeviceLost( OnLostDevice );
  244.     DXUTSetCallbackDeviceDestroyed( OnDestroyDevice );
  245.     DXUTSetCallbackMsgProc( MsgProc );
  246.     DXUTSetCallbackKeyboard( KeyboardProc );
  247.     DXUTSetCallbackFrameRender( OnFrameRender );
  248.     DXUTSetCallbackFrameMove( OnFrameMove );
  249.  
  250.     // Although multisampling is supported for render target surfaces, those surfaces
  251.     // exist without a parent texture, and must therefore be copied to a texture 
  252.     // surface if they're to be used as a source texture. This sample relies upon 
  253.     // several render targets being used as source textures, and therefore it makes
  254.     // sense to disable multisampling altogether.
  255.     CGrowableArray<D3DMULTISAMPLE_TYPE>* pMultiSampleTypeList = DXUTGetEnumeration()->GetPossibleMultisampleTypeList();
  256.     pMultiSampleTypeList->RemoveAll();
  257.     pMultiSampleTypeList->Add( D3DMULTISAMPLE_NONE );
  258.     DXUTGetEnumeration()->SetMultisampleQualityMax( 0 );
  259.  
  260.     // Show the cursor and clip it when in full screen
  261.     DXUTSetCursorSettings( true, true );
  262.  
  263.     InitApp();
  264.  
  265.     // Initialize the sample framework and create the desired Win32 window and Direct3D 
  266.     // device for the application. Calling each of these functions is optional, but they
  267.     // allow you to set several options which control the behavior of the framework.
  268.     DXUTInit( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
  269.     DXUTCreateWindow( L"HDRLighting" );
  270.     DXUTCreateDevice( D3DADAPTER_DEFAULT, true, 640, 480, IsDeviceAcceptable, ModifyDeviceSettings );
  271.  
  272.     // Pass control to the sample framework for handling the message pump and 
  273.     // dispatching render calls. The sample framework will call your FrameMove 
  274.     // and FrameRender callback when there is idle time between handling window messages.
  275.     DXUTMainLoop();
  276.  
  277.     // Perform any application-level cleanup here. Direct3D device resources are released within the
  278.     // appropriate callback functions and therefore don't require any cleanup code here.
  279.  
  280.     return DXUTGetExitCode();
  281. }
  282.  
  283.  
  284. //--------------------------------------------------------------------------------------
  285. // Initialize the app 
  286. //--------------------------------------------------------------------------------------
  287. void InitApp()
  288. {
  289.     // Initialize dialogs
  290.     g_HUD.SetCallback( OnGUIEvent ); int iY = 10; 
  291.     g_HUD.AddButton( IDC_TOGGLEFULLSCREEN, L"Toggle full screen", 35, iY, 125, 22 );
  292.     g_HUD.AddButton( IDC_TOGGLEREF, L"Toggle REF (F3)", 35, iY += 24, 125, 22 );
  293.     g_HUD.AddButton( IDC_CHANGEDEVICE, L"Change device (F2)", 35, iY += 24, 125, 22 );
  294.     g_HUD.AddButton( IDC_RESET, L"Reset Options (R)", 35, iY += 24, 125, 22, L'R' );
  295.     
  296.     // Title font for comboboxes
  297.     g_SampleUI.SetFont( 1, L"Arial", 14, FW_BOLD );
  298.     CDXUTElement* pElement = g_SampleUI.GetDefaultElement( DXUT_CONTROL_STATIC, 0 );
  299.     pElement->iFont = 1;
  300.     pElement->dwTextFormat = DT_LEFT | DT_BOTTOM;
  301.  
  302.     CDXUTComboBox* pComboBox = NULL;
  303.     g_SampleUI.SetCallback( OnGUIEvent ); iY = 10; 
  304.     g_SampleUI.AddStatic( IDC_STATIC, L"(G)lare Type", 35, iY += 24, 125, 22 );
  305.     g_SampleUI.AddComboBox( IDC_GLARETYPE, 35, iY += 24, 125, 22, L'G', false, &pComboBox );
  306.     g_SampleUI.AddStatic( IDC_LIGHT0_LABEL, L"Light 0", 35, iY += 24, 125, 22 );
  307.     g_SampleUI.AddSlider( IDC_LIGHT0, 35, iY += 24, 100, 22, 0, 90 );
  308.     g_SampleUI.AddStatic( IDC_LIGHT1_LABEL, L"Light 1", 35, iY += 24, 125, 22 );
  309.     g_SampleUI.AddSlider( IDC_LIGHT1, 35, iY += 24, 100, 22, 0, 90 );
  310.     g_SampleUI.AddStatic( IDC_KEYVALUE_LABEL, L"Key Value", 35, iY += 24, 125, 22 );
  311.     g_SampleUI.AddSlider( IDC_KEYVALUE, 35, iY += 24, 100, 22, 0, 100 );  
  312.     g_SampleUI.AddCheckBox( IDC_TONEMAP, L"(T)one Mapping", 35, iY += 34, 125, 20, true, L'T' );
  313.     g_SampleUI.AddCheckBox( IDC_BLUESHIFT, L"(B)lue Shift", 35, iY += 24, 125, 20, true, L'B' );
  314.     
  315.     pComboBox->AddItem( L"Disable", (void*) GLT_DISABLE );
  316.     pComboBox->AddItem( L"Camera", (void*) GLT_CAMERA );
  317.     pComboBox->AddItem( L"Natural Bloom", (void*) GLT_NATURAL );
  318.     pComboBox->AddItem( L"Cheap Lens", (void*) GLT_CHEAPLENS );
  319.     pComboBox->AddItem( L"Cross Screen", (void*) GLT_FILTER_CROSSSCREEN );
  320.     pComboBox->AddItem( L"Spectral Cross", (void*) GLT_FILTER_CROSSSCREEN_SPECTRAL );
  321.     pComboBox->AddItem( L"Snow Cross", (void*) GLT_FILTER_SNOWCROSS );
  322.     pComboBox->AddItem( L"Spectral Snow", (void*) GLT_FILTER_SNOWCROSS_SPECTRAL );
  323.     pComboBox->AddItem( L"Sunny Cross", (void*) GLT_FILTER_SUNNYCROSS );
  324.     pComboBox->AddItem( L"Spectral Sunny", (void*) GLT_FILTER_SUNNYCROSS_SPECTRAL );
  325.     pComboBox->AddItem( L"Cinema Vertical", (void*) GLT_CINECAM_VERTICALSLITS );
  326.     pComboBox->AddItem( L"Cinema Horizontal", (void*) GLT_CINECAM_HORIZONTALSLITS );
  327.     
  328.  
  329.     /*
  330.     g_SampleUI.AddComboBox( 19, 35, iY += 24, 125, 22 );
  331.     g_SampleUI.GetComboBox( 19 )->AddItem( L"Text1", NULL );
  332.     g_SampleUI.GetComboBox( 19 )->AddItem( L"Text2", NULL );
  333.     g_SampleUI.GetComboBox( 19 )->AddItem( L"Text3", NULL );
  334.     g_SampleUI.GetComboBox( 19 )->AddItem( L"Text4", NULL );
  335.     g_SampleUI.AddCheckBox( 21, L"Checkbox1", 35, iY += 24, 125, 22 );
  336.     g_SampleUI.AddCheckBox( 11, L"Checkbox2", 35, iY += 24, 125, 22 );
  337.     g_SampleUI.AddRadioButton( 12, 1, L"Radio1G1", 35, iY += 24, 125, 22 );
  338.     g_SampleUI.AddRadioButton( 13, 1, L"Radio2G1", 35, iY += 24, 125, 22 );
  339.     g_SampleUI.AddRadioButton( 14, 1, L"Radio3G1", 35, iY += 24, 125, 22 );
  340.     g_SampleUI.GetRadioButton( 14 )->SetChecked( true ); 
  341.     g_SampleUI.AddButton( 17, L"Button1", 35, iY += 24, 125, 22 );
  342.     g_SampleUI.AddButton( 18, L"Button2", 35, iY += 24, 125, 22 );
  343.     g_SampleUI.AddRadioButton( 15, 2, L"Radio1G2", 35, iY += 24, 125, 22 );
  344.     g_SampleUI.AddRadioButton( 16, 2, L"Radio2G3", 35, iY += 24, 125, 22 );
  345.     g_SampleUI.GetRadioButton( 16 )->SetChecked( true );
  346.     g_SampleUI.AddSlider( 20, 50, iY += 24, 100, 22 );
  347.     g_SampleUI.GetSlider( 20 )->SetRange( 0, 100 );
  348.     g_SampleUI.GetSlider( 20 )->SetValue( 50 );
  349. //    g_SampleUI.AddEditBox( 20, L"Test", 35, iY += 24, 125, 22 );
  350.     */
  351.  
  352.     // Set light positions in world space
  353.     g_avLightPosition[0] = D3DXVECTOR4(  4.0f,  2.0f,  18.0f, 1.0f );
  354.     g_avLightPosition[1] = D3DXVECTOR4(  11.0f, 2.0f,  18.0f, 1.0f );
  355.  
  356.     ResetOptions();
  357. }
  358.  
  359.  
  360. //-----------------------------------------------------------------------------
  361. // Name: ResetOptions()
  362. // Desc: Reset all user-controlled options to default values
  363. //-----------------------------------------------------------------------------
  364. void ResetOptions()
  365. {
  366.     g_bDrawHelp         = TRUE;
  367.     g_bDetailedStats    = TRUE;
  368.     
  369.     g_SampleUI.EnableNonUserEvents( true );
  370.  
  371.     g_SampleUI.GetCheckBox( IDC_TONEMAP )->SetChecked( true );
  372.     g_SampleUI.GetCheckBox( IDC_BLUESHIFT )->SetChecked( true );
  373.     g_SampleUI.GetSlider( IDC_LIGHT0 )->SetValue( 52 );
  374.     g_SampleUI.GetSlider( IDC_LIGHT1 )->SetValue( 43 );
  375.     g_SampleUI.GetSlider( IDC_KEYVALUE )->SetValue( 18 );
  376.     g_SampleUI.GetComboBox( IDC_GLARETYPE )->SetSelectedByData( (void*) GLT_DEFAULT );
  377.     
  378.     g_SampleUI.EnableNonUserEvents( false );
  379. }
  380.  
  381.  
  382. //-----------------------------------------------------------------------------
  383. // Name: AdjustLight
  384. // Desc: Increment or decrement the light at the given index
  385. //-----------------------------------------------------------------------------
  386. HRESULT AdjustLight(UINT iLight, bool bIncrement)
  387. {
  388.     if( iLight >= NUM_LIGHTS )
  389.         return E_INVALIDARG;
  390.  
  391.     if( bIncrement && g_nLightLogIntensity[iLight] < 7 )
  392.     {
  393.         g_nLightMantissa[iLight]++;
  394.         if( g_nLightMantissa[iLight] > 9 )
  395.         {
  396.             g_nLightMantissa[iLight] = 1;
  397.             g_nLightLogIntensity[iLight]++;
  398.         }
  399.     }
  400.     
  401.     if( !bIncrement && g_nLightLogIntensity[iLight] > -4 )
  402.     {
  403.         g_nLightMantissa[iLight]--;
  404.         if( g_nLightMantissa[iLight] < 1 )
  405.         {
  406.             g_nLightMantissa[iLight] = 9;
  407.             g_nLightLogIntensity[iLight]--;
  408.         }
  409.     }
  410.  
  411.     RefreshLights();
  412.     return S_OK;
  413. }
  414.  
  415.  
  416. //-----------------------------------------------------------------------------
  417. // Name: RefreshLights
  418. // Desc: Set the light intensities to match the current log luminance
  419. //-----------------------------------------------------------------------------
  420. HRESULT RefreshLights()
  421. {
  422.     CDXUTStatic* pStatic = NULL;
  423.     WCHAR strBuffer[256] = {0};
  424.         
  425.     for( int i=0; i < NUM_LIGHTS; i++ )
  426.     {
  427.         g_avLightIntensity[i].x = g_nLightMantissa[i] * (float) pow(10.0f, g_nLightLogIntensity[i]);
  428.         g_avLightIntensity[i].y = g_nLightMantissa[i] * (float) pow(10.0f, g_nLightLogIntensity[i]);
  429.         g_avLightIntensity[i].z = g_nLightMantissa[i] * (float) pow(10.0f, g_nLightLogIntensity[i]);
  430.         g_avLightIntensity[i].w = 1.0f;
  431.  
  432.         _snwprintf( strBuffer, 255, L"Light %d: %d.0e%d", i, g_nLightMantissa[i], g_nLightLogIntensity[i] );
  433.         pStatic = g_SampleUI.GetStatic( IDC_LIGHT0_LABEL + i );
  434.         pStatic->SetText( strBuffer );
  435.             
  436.     }
  437.     
  438.     return S_OK;
  439. }
  440.  
  441.  
  442. //--------------------------------------------------------------------------------------
  443. // Called during device initialization, this code checks the device for some 
  444. // minimum set of capabilities, and rejects those that don't pass by returning false.
  445. //--------------------------------------------------------------------------------------
  446. bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, 
  447.                                   D3DFORMAT BackBufferFormat, bool bWindowed )
  448. {
  449.     // Skip backbuffer formats that don't support alpha blending
  450.     IDirect3D9* pD3D = DXUTGetD3DObject(); 
  451.     if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
  452.                     AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, 
  453.                     D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
  454.         return false;
  455.  
  456.     if(pCaps->PixelShaderVersion < D3DPS_VERSION(2,0))
  457.         return false;
  458.  
  459.     // No fallback yet, so need to support D3DFMT_A16B16G16R16F render target
  460.     if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
  461.                     AdapterFormat, D3DUSAGE_RENDERTARGET, 
  462.                     D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F) ) )
  463.     {
  464.         return false;
  465.     }
  466.  
  467.     // No fallback yet, so need to support D3DFMT_R32F or D3DFMT_R16F render target
  468.     if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
  469.                     AdapterFormat, D3DUSAGE_RENDERTARGET, 
  470.                     D3DRTYPE_TEXTURE, D3DFMT_R32F) ) )
  471.     {
  472.         if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
  473.                         AdapterFormat, D3DUSAGE_RENDERTARGET, 
  474.                         D3DRTYPE_TEXTURE, D3DFMT_R16F) ) )
  475.             return false;
  476.     }
  477.  
  478.  
  479.     // Need to support post-pixel processing
  480.     if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
  481.         AdapterFormat, D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, 
  482.         D3DRTYPE_SURFACE, BackBufferFormat ) ) )
  483.     {
  484.         return false;
  485.     }
  486.  
  487.  
  488.     return true;
  489. }
  490.  
  491.  
  492. //--------------------------------------------------------------------------------------
  493. // This callback function is called immediately before a device is created to allow the 
  494. // application to modify the device settings. The supplied pDeviceSettings parameter 
  495. // contains the settings that the framework has selected for the new device, and the 
  496. // application can make any desired changes directly to this structure.  Note however that 
  497. // the sample framework will not correct invalid device settings so care must be taken 
  498. // to return valid device settings, otherwise IDirect3D9::CreateDevice() will fail.  
  499. //--------------------------------------------------------------------------------------
  500. void CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps )
  501. {
  502.     // If device doesn't support HW T&L or doesn't support 2.0 vertex shaders in HW 
  503.     // then switch to SWVP.
  504.     if( (pCaps->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 ||
  505.          pCaps->VertexShaderVersion < D3DVS_VERSION(2,0) )
  506.     {
  507.         pDeviceSettings->BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  508.     }
  509.     else
  510.     {
  511.         pDeviceSettings->BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
  512.     }
  513.     
  514.     // This application is designed to work on a pure device by not using 
  515.     // IDirect3D9::Get*() methods, so create a pure device if supported and using HWVP.
  516.     if ((pCaps->DevCaps & D3DDEVCAPS_PUREDEVICE) != 0 && 
  517.         (pDeviceSettings->BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) != 0 )
  518.         pDeviceSettings->BehaviorFlags |= D3DCREATE_PUREDEVICE;
  519.  
  520.     // Debugging vertex shaders requires either REF or software vertex processing 
  521.     // and debugging pixel shaders requires REF.  
  522. #ifdef DEBUG_VS
  523.     if( pDeviceSettings->DeviceType != D3DDEVTYPE_REF )
  524.     {
  525.         pDeviceSettings->BehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING;
  526.         pDeviceSettings->BehaviorFlags &= ~D3DCREATE_PUREDEVICE;                            
  527.         pDeviceSettings->BehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  528.     }
  529. #endif
  530. #ifdef DEBUG_PS
  531.     pDeviceSettings->DeviceType = D3DDEVTYPE_REF;
  532. #endif
  533.  
  534. }
  535.  
  536.  
  537. //--------------------------------------------------------------------------------------
  538. // This callback function will be called immediately after the Direct3D device has been 
  539. // created, which will happen during application initialization and windowed/full screen 
  540. // toggles. This is the best location to create D3DPOOL_MANAGED resources since these 
  541. // resources need to be reloaded whenever the device is destroyed. Resources created  
  542. // here should be released in the OnDestroyDevice callback. 
  543. //--------------------------------------------------------------------------------------
  544. HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  545. {
  546.     HRESULT hr;
  547.  
  548.     // Determine which of D3DFMT_R16F or D3DFMT_R32F to use for luminance texture
  549.     D3DCAPS9 Caps;
  550.     IDirect3D9* pD3D;
  551.     D3DDISPLAYMODE DisplayMode;
  552.     pd3dDevice->GetDeviceCaps( &Caps );
  553.     pd3dDevice->GetDirect3D( &pD3D );
  554.     pd3dDevice->GetDisplayMode( 0, &DisplayMode );
  555.     // IsDeviceAcceptable already ensured that one of D3DFMT_R16F or D3DFMT_R32F is available.
  556.     if( FAILED( pD3D->CheckDeviceFormat( Caps.AdapterOrdinal, Caps.DeviceType,
  557.                     DisplayMode.Format, D3DUSAGE_RENDERTARGET, 
  558.                     D3DRTYPE_TEXTURE, D3DFMT_R16F ) ) )
  559.         g_LuminanceFormat = D3DFMT_R32F;
  560.     else
  561.         g_LuminanceFormat = D3DFMT_R16F;
  562.  
  563.     SAFE_RELEASE( pD3D );
  564.  
  565.     // Initialize the font
  566.     V_RETURN( D3DXCreateFont( pd3dDevice, 15, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, 
  567.                          OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, 
  568.                          L"Arial", &g_pFont ) );
  569.  
  570.     // Define DEBUG_VS and/or DEBUG_PS to debug vertex and/or pixel shaders with the 
  571.     // shader debugger. Debugging vertex shaders requires either REF or software vertex 
  572.     // processing, and debugging pixel shaders requires REF.  The 
  573.     // D3DXSHADER_FORCE_*_SOFTWARE_NOOPT flag improves the debug experience in the 
  574.     // shader debugger.  It enables source level debugging, prevents instruction 
  575.     // reordering, prevents dead code elimination, and forces the compiler to compile 
  576.     // against the next higher available software target, which ensures that the 
  577.     // unoptimized shaders do not exceed the shader model limitations.  Setting these 
  578.     // flags will cause slower rendering since the shaders will be unoptimized and 
  579.     // forced into software.  See the DirectX documentation for more information about 
  580.     // using the shader debugger.
  581.     DWORD dwShaderFlags = 0;
  582.     #ifdef DEBUG_VS
  583.         dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
  584.     #endif
  585.     #ifdef DEBUG_PS
  586.         dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;
  587.     #endif
  588.  
  589.     // Read the D3DX effect file
  590.     WCHAR str[MAX_PATH];
  591.     V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"HDRLighting.fx" ) );
  592.  
  593.     // If this fails, there should be debug output as to 
  594.     // they the .fx file failed to compile
  595.     V_RETURN( D3DXCreateEffectFromFile( pd3dDevice, str, NULL, NULL, dwShaderFlags, 
  596.                                         NULL, &g_pEffect, NULL ) );
  597.  
  598.     // Initialize the camera
  599.     D3DXVECTOR3   vFromPt(7.5f, 1.8f, 2);
  600.     D3DXVECTOR3   vLookatPt(7.5f, 1.5f, 10.0f);
  601.     g_Camera.SetViewParams( &vFromPt, &vLookatPt );
  602.  
  603.     // Set options for the first-person camera
  604.     g_Camera.SetScalers( 0.01f, 15.0f );
  605.     g_Camera.SetDrag( true );
  606.     g_Camera.SetEnableYAxisMovement(false);
  607.  
  608.     D3DXVECTOR3 vMin = D3DXVECTOR3(1.5f,0.0f,1.5f);
  609.     D3DXVECTOR3 vMax = D3DXVECTOR3(13.5f,10.0f,18.5f);
  610.     g_Camera.SetClipToBoundary( TRUE, &vMin, &vMax ); 
  611.  
  612.  
  613.     return S_OK;
  614. }
  615.  
  616.  
  617. //--------------------------------------------------------------------------------------
  618. // This function loads the mesh and ensures the mesh has normals; it also optimizes the 
  619. // mesh for the graphics card's vertex cache, which improves performance by organizing 
  620. // the internal triangle list for less cache misses.
  621. //--------------------------------------------------------------------------------------
  622. HRESULT LoadMesh( IDirect3DDevice9* pd3dDevice, WCHAR* strFileName, ID3DXMesh** ppMesh )
  623. {
  624.     ID3DXMesh* pMesh = NULL;
  625.     WCHAR str[MAX_PATH];
  626.     HRESULT hr;
  627.  
  628.     // Load the mesh with D3DX and get back a ID3DXMesh*.  For this
  629.     // sample we'll ignore the X file's embedded materials since we know 
  630.     // exactly the model we're loading.  See the mesh samples such as
  631.     // "OptimizedMesh" for a more generic mesh loading example.
  632.     V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, strFileName ) );
  633.  
  634.     V_RETURN( D3DXLoadMeshFromX(str, D3DXMESH_MANAGED, pd3dDevice, NULL, NULL, NULL, NULL, &pMesh) );
  635.  
  636.     DWORD *rgdwAdjacency = NULL;
  637.  
  638.     // Make sure there are normals which are required for lighting
  639.     if( !(pMesh->GetFVF() & D3DFVF_NORMAL) )
  640.     {
  641.         ID3DXMesh* pTempMesh;
  642.         V( pMesh->CloneMeshFVF( pMesh->GetOptions(), 
  643.                                   pMesh->GetFVF() | D3DFVF_NORMAL, 
  644.                                   pd3dDevice, &pTempMesh ) );
  645.         V( D3DXComputeNormals( pTempMesh, NULL ) );
  646.  
  647.         SAFE_RELEASE( pMesh );
  648.         pMesh = pTempMesh;
  649.     }
  650.  
  651.     // Optimize the mesh for this graphics card's vertex cache 
  652.     // so when rendering the mesh's triangle list the vertices will 
  653.     // cache hit more often so it won't have to re-execute the vertex shader 
  654.     // on those vertices so it will improve perf.     
  655.     rgdwAdjacency = new DWORD[pMesh->GetNumFaces() * 3];
  656.     if( rgdwAdjacency == NULL )
  657.         return E_OUTOFMEMORY;
  658.     V( pMesh->ConvertPointRepsToAdjacency(NULL, rgdwAdjacency) );
  659.     V( pMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE, rgdwAdjacency, NULL, NULL, NULL) );
  660.     delete []rgdwAdjacency;
  661.  
  662.     *ppMesh = pMesh;
  663.  
  664.     return S_OK;
  665. }
  666.  
  667.  
  668. //--------------------------------------------------------------------------------------
  669. // This callback function will be called immediately after the Direct3D device has been 
  670. // reset, which will happen after a lost device scenario. This is the best location to 
  671. // create D3DPOOL_DEFAULT resources since these resources need to be reloaded whenever 
  672. // the device is lost. Resources created here should be released in the OnLostDevice 
  673. // callback. 
  674. //--------------------------------------------------------------------------------------
  675. HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, 
  676.                                 const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  677. {
  678.     HRESULT hr;
  679.     int i=0; // loop variable
  680.  
  681.     g_pd3dDevice = pd3dDevice;
  682.  
  683.     if( g_pFont )
  684.         V_RETURN( g_pFont->OnResetDevice() );
  685.     if( g_pEffect )
  686.         V_RETURN( g_pEffect->OnResetDevice() );
  687.  
  688.     // Create a sprite to help batch calls when drawing many lines of text
  689.     V_RETURN( D3DXCreateSprite( pd3dDevice, &g_pTextSprite ) );
  690.  
  691.     const D3DSURFACE_DESC* pBackBufferDesc = DXUTGetBackBufferSurfaceDesc();
  692.  
  693.     // Crop the scene texture so width and height are evenly divisible by 8.
  694.     // This cropped version of the scene will be used for post processing effects,
  695.     // and keeping everything evenly divisible allows precise control over
  696.     // sampling points within the shaders.
  697.     g_dwCropWidth = pBackBufferDesc->Width - pBackBufferDesc->Width % 8;
  698.     g_dwCropHeight = pBackBufferDesc->Height - pBackBufferDesc->Height % 8;
  699.  
  700.     // Create the HDR scene texture
  701.     hr = g_pd3dDevice->CreateTexture(pBackBufferDesc->Width, pBackBufferDesc->Height, 
  702.                                      1, D3DUSAGE_RENDERTARGET, D3DFMT_A16B16G16R16F, 
  703.                                      D3DPOOL_DEFAULT, &g_pTexScene, NULL);
  704.     if( FAILED(hr) )
  705.         return hr;
  706.  
  707.  
  708.     // Scaled version of the HDR scene texture
  709.     hr = g_pd3dDevice->CreateTexture(g_dwCropWidth / 4, g_dwCropHeight / 4, 
  710.                                      1, D3DUSAGE_RENDERTARGET, 
  711.                                      D3DFMT_A16B16G16R16F, D3DPOOL_DEFAULT, 
  712.                                      &g_pTexSceneScaled, NULL);
  713.     if( FAILED(hr) )
  714.         return hr;
  715.     
  716.  
  717.     // Create the bright-pass filter texture. 
  718.     // Texture has a black border of single texel thickness to fake border 
  719.     // addressing using clamp addressing
  720.     hr = g_pd3dDevice->CreateTexture(g_dwCropWidth / 4 + 2, g_dwCropHeight / 4 + 2, 
  721.                                      1, D3DUSAGE_RENDERTARGET, 
  722.                                      D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, 
  723.                                      &g_pTexBrightPass, NULL);
  724.     if( FAILED(hr) )
  725.         return hr;
  726.  
  727.     
  728.     
  729.     // Create a texture to be used as the source for the star effect
  730.     // Texture has a black border of single texel thickness to fake border 
  731.     // addressing using clamp addressing
  732.     hr = g_pd3dDevice->CreateTexture(g_dwCropWidth / 4 + 2, g_dwCropHeight / 4 + 2, 
  733.                                      1, D3DUSAGE_RENDERTARGET, 
  734.                                      D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, 
  735.                                      &g_pTexStarSource, NULL);
  736.     if( FAILED(hr) )
  737.         return hr;
  738.  
  739.     
  740.     
  741.     // Create a texture to be used as the source for the bloom effect
  742.     // Texture has a black border of single texel thickness to fake border 
  743.     // addressing using clamp addressing
  744.     hr = g_pd3dDevice->CreateTexture(g_dwCropWidth / 8 + 2, g_dwCropHeight / 8 + 2, 
  745.                                      1, D3DUSAGE_RENDERTARGET, 
  746.                                      D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, 
  747.                                      &g_pTexBloomSource, NULL);
  748.     if( FAILED(hr) )
  749.         return hr;
  750.  
  751.  
  752.     
  753.  
  754.     // Create a 2 textures to hold the luminance that the user is currently adapted
  755.     // to. This allows for a simple simulation of light adaptation.
  756.     hr = g_pd3dDevice->CreateTexture(1, 1, 1, D3DUSAGE_RENDERTARGET,
  757.                                      g_LuminanceFormat, D3DPOOL_DEFAULT,
  758.                                      &g_pTexAdaptedLuminanceCur, NULL);
  759.     if( FAILED(hr) )
  760.         return hr;
  761.     hr = g_pd3dDevice->CreateTexture(1, 1, 1, D3DUSAGE_RENDERTARGET,
  762.                                      g_LuminanceFormat, D3DPOOL_DEFAULT,
  763.                                      &g_pTexAdaptedLuminanceLast, NULL);
  764.     if( FAILED(hr) )
  765.         return hr;
  766.  
  767.  
  768.     // For each scale stage, create a texture to hold the intermediate results
  769.     // of the luminance calculation
  770.     for(i=0; i < NUM_TONEMAP_TEXTURES; i++)
  771.     {
  772.         int iSampleLen = 1 << (2*i);
  773.  
  774.         hr = g_pd3dDevice->CreateTexture(iSampleLen, iSampleLen, 1, D3DUSAGE_RENDERTARGET, 
  775.                                          g_LuminanceFormat, D3DPOOL_DEFAULT, 
  776.                                          &g_apTexToneMap[i], NULL);
  777.         if( FAILED(hr) )
  778.             return hr;
  779.     }
  780.  
  781.  
  782.     // Create the temporary blooming effect textures
  783.     // Texture has a black border of single texel thickness to fake border 
  784.     // addressing using clamp addressing
  785.     for( i=1; i < NUM_BLOOM_TEXTURES; i++ )
  786.     {
  787.         hr = g_pd3dDevice->CreateTexture(g_dwCropWidth/8 + 2, g_dwCropHeight/8 + 2, 
  788.                                         1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, 
  789.                                         D3DPOOL_DEFAULT, &g_apTexBloom[i], NULL);
  790.         if( FAILED(hr) )
  791.             return hr;
  792.     }
  793.  
  794.     // Create the final blooming effect texture
  795.     hr = g_pd3dDevice->CreateTexture( g_dwCropWidth/8, g_dwCropHeight/8,
  796.                                       1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, 
  797.                                       D3DPOOL_DEFAULT, &g_apTexBloom[0], NULL);
  798.     if( FAILED(hr) )
  799.         return hr;
  800.                               
  801.  
  802.     // Create the star effect textures
  803.     for( i=0; i < NUM_STAR_TEXTURES; i++ )
  804.     {
  805.         hr = g_pd3dDevice->CreateTexture( g_dwCropWidth /4, g_dwCropHeight / 4,
  806.                                           1, D3DUSAGE_RENDERTARGET,
  807.                                           D3DFMT_A16B16G16R16F, D3DPOOL_DEFAULT,
  808.                                           &g_apTexStar[i], NULL );
  809.  
  810.         if( FAILED(hr) )
  811.             return hr;
  812.     }
  813.  
  814.     // Create a texture to paint the walls
  815.     TCHAR Path[MAX_PATH];
  816.     DXUTFindDXSDKMediaFileCch(Path, MAX_PATH, TEXT("misc\\env2.bmp"));
  817.  
  818.     hr = D3DXCreateTextureFromFile( g_pd3dDevice, Path, &g_pTexWall );
  819.     if( FAILED(hr) )
  820.         return hr;
  821.  
  822.  
  823.     // Create a texture to paint the floor
  824.     DXUTFindDXSDKMediaFileCch(Path, MAX_PATH, TEXT("misc\\ground2.bmp"));
  825.  
  826.     hr = D3DXCreateTextureFromFile( g_pd3dDevice, Path, &g_pTexFloor );
  827.     if( FAILED(hr) )
  828.         return hr;
  829.  
  830.  
  831.     // Create a texture to paint the ceiling
  832.     DXUTFindDXSDKMediaFileCch(Path, MAX_PATH, TEXT("misc\\seafloor.bmp"));
  833.  
  834.     hr = D3DXCreateTextureFromFile( g_pd3dDevice, Path, &g_pTexCeiling );
  835.     if( FAILED(hr) )
  836.         return hr;
  837.  
  838.  
  839.     // Create a texture for the paintings
  840.     DXUTFindDXSDKMediaFileCch(Path, MAX_PATH, TEXT("misc\\env3.bmp"));
  841.  
  842.     hr = D3DXCreateTextureFromFile( g_pd3dDevice, Path, &g_pTexPainting );
  843.     if( FAILED(hr) )
  844.         return hr;
  845.  
  846.  
  847.     // Textures with borders must be cleared since scissor rect testing will
  848.     // be used to avoid rendering on top of the border
  849.     ClearTexture( g_pTexAdaptedLuminanceCur );
  850.     ClearTexture( g_pTexAdaptedLuminanceLast );
  851.     ClearTexture( g_pTexBloomSource );
  852.     ClearTexture( g_pTexBrightPass );
  853.     ClearTexture( g_pTexStarSource );
  854.  
  855.     for( i=0; i < NUM_BLOOM_TEXTURES; i++ )
  856.     {
  857.         ClearTexture( g_apTexBloom[i] );
  858.     }
  859.    
  860.     
  861.     // Build the world object
  862.     hr = BuildWorldMesh();
  863.     if( FAILED(hr) )
  864.         return hr;
  865.  
  866.  
  867.     // Create sphere mesh to represent the light
  868.     hr = LoadMesh(g_pd3dDevice, TEXT("misc\\sphere0.x"), &g_pmeshSphere);
  869.     if( FAILED(hr) )
  870.         return hr;
  871.  
  872.     // Set effect file variables
  873.     D3DXMATRIX mProjection = *g_Camera.GetProjMatrix();
  874.     g_pEffect->SetMatrix("g_mProjection", &mProjection);
  875.     g_pEffect->SetFloat( "g_fBloomScale", 1.0f );
  876.     g_pEffect->SetFloat( "g_fStarScale", 0.5f );
  877.  
  878.     // Setup the camera's projection parameters
  879.     float fAspectRatio = ((FLOAT)g_dwCropWidth) / g_dwCropHeight;
  880.     g_Camera.SetProjParams( D3DX_PI/4, fAspectRatio, 0.2f, 30.0f );
  881.     
  882.     g_HUD.SetLocation( pBackBufferSurfaceDesc->Width-170, 0 );
  883.     g_HUD.SetSize( 170, 170 );
  884.     g_SampleUI.SetLocation( pBackBufferSurfaceDesc->Width-170, pBackBufferSurfaceDesc->Height-350 );
  885.     g_SampleUI.SetSize( 170, 300 );
  886.  
  887.     return S_OK;
  888. }
  889.  
  890.  
  891. //-----------------------------------------------------------------------------
  892. // Name: ClearTexture()
  893. // Desc: Helper function for RestoreDeviceObjects to clear a texture surface
  894. //-----------------------------------------------------------------------------
  895. HRESULT ClearTexture( LPDIRECT3DTEXTURE9 pTexture )
  896. {
  897.     HRESULT hr = S_OK;
  898.     PDIRECT3DSURFACE9 pSurface = NULL;
  899.  
  900.     hr = pTexture->GetSurfaceLevel( 0, &pSurface );
  901.     if( SUCCEEDED(hr) )
  902.         g_pd3dDevice->ColorFill( pSurface, NULL, D3DCOLOR_ARGB(0, 0, 0, 0) );
  903.  
  904.     SAFE_RELEASE( pSurface );
  905.     return hr;
  906. }
  907.  
  908.  
  909. //-----------------------------------------------------------------------------
  910. // Name: BuildWorldMesh()
  911. // Desc: Creates the wall, floor, ceiling, columns, and painting mesh
  912. //-----------------------------------------------------------------------------
  913. HRESULT BuildWorldMesh()
  914. {
  915.     HRESULT hr;
  916.     UINT i; // Loop variable
  917.     
  918.     const FLOAT fWidth  = 15.0f;
  919.     const FLOAT fDepth  = 20.0f;
  920.     const FLOAT fHeight = 3.0f;
  921.  
  922.     // Create the room  
  923.     LPD3DXMESH pWorldMeshTemp = NULL;
  924.     hr = D3DXCreateMeshFVF( 48, 96, 0, WorldVertex::FVF, g_pd3dDevice, &pWorldMeshTemp );
  925.     if( FAILED(hr) )
  926.         goto LCleanReturn;
  927.  
  928.     WorldVertex* pVertex;
  929.     hr = pWorldMeshTemp->LockVertexBuffer(0, (PVOID*)&pVertex);
  930.     if( FAILED(hr) )
  931.         goto LCleanReturn;
  932.  
  933.     WorldVertex* pV;
  934.     pV = pVertex;
  935.  
  936.     // Front wall
  937.     SetTextureCoords( pV, 7.0f, 2.0f );
  938.     (pV++)->p = D3DXVECTOR3( 0.0f,   fHeight, fDepth );   
  939.     (pV++)->p = D3DXVECTOR3( fWidth, fHeight, fDepth );  
  940.     (pV++)->p = D3DXVECTOR3( fWidth, 0.0f,    fDepth );  
  941.     (pV++)->p = D3DXVECTOR3( 0.0f,   0.0f,    fDepth );  
  942.  
  943.     // Right wall
  944.     SetTextureCoords( pV, 10.5f, 2.0f );
  945.     (pV++)->p = D3DXVECTOR3( fWidth, fHeight, fDepth );
  946.     (pV++)->p = D3DXVECTOR3( fWidth, fHeight, 0.0f   );
  947.     (pV++)->p = D3DXVECTOR3( fWidth, 0.0f,    0.0f   );
  948.     (pV++)->p = D3DXVECTOR3( fWidth, 0.0f,    fDepth );
  949.  
  950.     // Back wall
  951.     SetTextureCoords( pV, 7.0f, 2.0f );
  952.     (pV++)->p = D3DXVECTOR3( fWidth, fHeight, 0.0f   );
  953.     (pV++)->p = D3DXVECTOR3( 0.0f,   fHeight, 0.0f   );
  954.     (pV++)->p = D3DXVECTOR3( 0.0f,   0.0f,    0.0f   );
  955.     (pV++)->p = D3DXVECTOR3( fWidth, 0.0f,    0.0f   );
  956.  
  957.     // Left wall
  958.     SetTextureCoords( pV, 10.5f, 2.0f );
  959.     (pV++)->p = D3DXVECTOR3( 0.0f,   fHeight, 0.0f   );
  960.     (pV++)->p = D3DXVECTOR3( 0.0f,   fHeight, fDepth );
  961.     (pV++)->p = D3DXVECTOR3( 0.0f,   0.0f,    fDepth );
  962.     (pV++)->p = D3DXVECTOR3( 0.0f,   0.0f,    0.0f   );
  963.  
  964.     BuildColumn( pV, 4.0f, fHeight, 7.0f, 0.75f );
  965.     BuildColumn( pV, 4.0f, fHeight, 13.0f, 0.75f );
  966.     BuildColumn( pV, 11.0f, fHeight, 7.0f, 0.75f );
  967.     BuildColumn( pV, 11.0f, fHeight, 13.0f, 0.75f );
  968.  
  969.     // Floor
  970.     SetTextureCoords( pV, 7.0f, 7.0f );
  971.     (pV++)->p = D3DXVECTOR3( 0.0f,   0.0f,    fDepth );
  972.     (pV++)->p = D3DXVECTOR3( fWidth, 0.0f,    fDepth );
  973.     (pV++)->p = D3DXVECTOR3( fWidth, 0.0f,    0.0f   );
  974.     (pV++)->p = D3DXVECTOR3( 0.0f,   0.0f,    0.0f   );
  975.  
  976.     // Ceiling
  977.     SetTextureCoords( pV, 7.0f, 2.0f );
  978.     (pV++)->p = D3DXVECTOR3( 0.0f,   fHeight, 0.0f   );
  979.     (pV++)->p = D3DXVECTOR3( fWidth, fHeight, 0.0f   );
  980.     (pV++)->p = D3DXVECTOR3( fWidth, fHeight, fDepth );
  981.     (pV++)->p = D3DXVECTOR3( 0.0f,   fHeight, fDepth );
  982.  
  983.     // Painting 1
  984.     SetTextureCoords( pV, 1.0f, 1.0f );
  985.     (pV++)->p = D3DXVECTOR3( 2.0f,   fHeight - 0.5f, fDepth - 0.01f );
  986.     (pV++)->p = D3DXVECTOR3( 6.0f,   fHeight - 0.5f, fDepth - 0.01f );
  987.     (pV++)->p = D3DXVECTOR3( 6.0f,   fHeight - 2.5f, fDepth - 0.01f );
  988.     (pV++)->p = D3DXVECTOR3( 2.0f,   fHeight - 2.5f, fDepth - 0.01f );
  989.  
  990.     // Painting 2
  991.     SetTextureCoords( pV, 1.0f, 1.0f );
  992.     (pV++)->p = D3DXVECTOR3(  9.0f,   fHeight - 0.5f, fDepth - 0.01f );
  993.     (pV++)->p = D3DXVECTOR3( 13.0f,   fHeight - 0.5f, fDepth - 0.01f );
  994.     (pV++)->p = D3DXVECTOR3( 13.0f,   fHeight - 2.5f, fDepth - 0.01f );
  995.     (pV++)->p = D3DXVECTOR3(  9.0f,   fHeight - 2.5f, fDepth - 0.01f );
  996.  
  997.     pWorldMeshTemp->UnlockVertexBuffer();
  998.  
  999.     // Retrieve the indices
  1000.     WORD* pIndex;
  1001.     hr = pWorldMeshTemp->LockIndexBuffer(0, (PVOID*)&pIndex);
  1002.     if(FAILED(hr))
  1003.         goto LCleanReturn;
  1004.  
  1005.     for( i=0; i < pWorldMeshTemp->GetNumFaces()/2; i++ )
  1006.     {
  1007.         *pIndex++ = (i*4) + 0;
  1008.         *pIndex++ = (i*4) + 1;
  1009.         *pIndex++ = (i*4) + 2;
  1010.         *pIndex++ = (i*4) + 0;
  1011.         *pIndex++ = (i*4) + 2;
  1012.         *pIndex++ = (i*4) + 3;
  1013.     }
  1014.  
  1015.     pWorldMeshTemp->UnlockIndexBuffer();
  1016.     
  1017.     // Set attribute groups to draw floor, ceiling, walls, and paintings
  1018.     // separately, with different shader constants. These group numbers
  1019.     // will be used during the calls to DrawSubset().
  1020.     DWORD* pAttribs;
  1021.     hr = pWorldMeshTemp->LockAttributeBuffer(0, &pAttribs);
  1022.     if( FAILED(hr) )
  1023.         goto LCleanReturn;
  1024.  
  1025.     for( i=0; i < 40; i++ )
  1026.         *pAttribs++ = 0;
  1027.  
  1028.     for( i=0; i < 2; i++ )
  1029.         *pAttribs++ = 1;
  1030.  
  1031.     for( i=0; i < 2; i++ )
  1032.         *pAttribs++ = 2;
  1033.  
  1034.     for( i=0; i < 4; i++ )
  1035.         *pAttribs++ = 3;
  1036.  
  1037.     pWorldMeshTemp->UnlockAttributeBuffer();
  1038.     D3DXComputeNormals( pWorldMeshTemp, NULL );
  1039.  
  1040.     // Optimize the mesh
  1041.     hr = pWorldMeshTemp->CloneMeshFVF( D3DXMESH_VB_WRITEONLY | D3DXMESH_IB_WRITEONLY, 
  1042.                                        WorldVertex::FVF, g_pd3dDevice, &g_pWorldMesh );
  1043.     if( FAILED(hr) )
  1044.         goto LCleanReturn;
  1045.  
  1046.     hr = S_OK;
  1047.  
  1048. LCleanReturn:
  1049.     SAFE_RELEASE( pWorldMeshTemp );
  1050.     return hr;
  1051. }
  1052.  
  1053. //-----------------------------------------------------------------------------
  1054. // Name: BuildColumn()
  1055. // Desc: Helper function for BuildWorldMesh to add column quads to the scene 
  1056. //-----------------------------------------------------------------------------
  1057. HRESULT BuildColumn( WorldVertex* &pV, float x, float y, float z, float width )
  1058. {
  1059.     float w = width / 2;
  1060.  
  1061.     SetTextureCoords( pV, 1.0f, 2.0f );
  1062.     (pV++)->p = D3DXVECTOR3( x - w, y,    z - w );
  1063.     (pV++)->p = D3DXVECTOR3( x + w, y,    z - w );
  1064.     (pV++)->p = D3DXVECTOR3( x + w, 0.0f, z - w );
  1065.     (pV++)->p = D3DXVECTOR3( x - w, 0.0f, z - w );
  1066.  
  1067.     SetTextureCoords( pV, 1.0f, 2.0f );
  1068.     (pV++)->p = D3DXVECTOR3( x + w, y,    z - w );
  1069.     (pV++)->p = D3DXVECTOR3( x + w, y,    z + w );
  1070.     (pV++)->p = D3DXVECTOR3( x + w, 0.0f, z + w );
  1071.     (pV++)->p = D3DXVECTOR3( x + w, 0.0f, z - w );
  1072.  
  1073.     SetTextureCoords( pV, 1.0f, 2.0f );
  1074.     (pV++)->p = D3DXVECTOR3( x + w, y,    z + w );
  1075.     (pV++)->p = D3DXVECTOR3( x - w, y,    z + w );
  1076.     (pV++)->p = D3DXVECTOR3( x - w, 0.0f, z + w );
  1077.     (pV++)->p = D3DXVECTOR3( x + w, 0.0f, z + w );
  1078.  
  1079.     SetTextureCoords( pV, 1.0f, 2.0f );
  1080.     (pV++)->p = D3DXVECTOR3( x - w, y,    z + w );
  1081.     (pV++)->p = D3DXVECTOR3( x - w, y,    z - w );
  1082.     (pV++)->p = D3DXVECTOR3( x - w, 0.0f, z - w );
  1083.     (pV++)->p = D3DXVECTOR3( x - w, 0.0f, z + w );
  1084.  
  1085.     return S_OK;
  1086. }
  1087.  
  1088.  
  1089. //-----------------------------------------------------------------------------
  1090. // Name: SetTextureCoords()
  1091. // Desc: Helper function for BuildWorldMesh to set texture coordinates
  1092. //       for vertices
  1093. //-----------------------------------------------------------------------------
  1094. void SetTextureCoords( WorldVertex* pVertex, float u, float v )
  1095. {
  1096.     (pVertex++)->t = D3DXVECTOR2( 0.0f, 0.0f );
  1097.     (pVertex++)->t = D3DXVECTOR2( u,    0.0f );
  1098.     (pVertex++)->t = D3DXVECTOR2( u,    v    );
  1099.     (pVertex++)->t = D3DXVECTOR2( 0.0f, v    );
  1100. }
  1101.  
  1102.  
  1103. //--------------------------------------------------------------------------------------
  1104. // This callback function will be called once at the beginning of every frame. This is the
  1105. // best location for your application to handle updates to the scene, but is not 
  1106. // intended to contain actual rendering calls, which should instead be placed in the 
  1107. // OnFrameRender callback.  
  1108. //--------------------------------------------------------------------------------------
  1109. void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  1110. {
  1111.     // Update the camera's position based on user input 
  1112.     g_Camera.FrameMove( fElapsedTime );
  1113.  
  1114.     // Set the flag to refresh the user's simulated adaption level.
  1115.     // Frame move is not called when the scene is paused or single-stepped. 
  1116.     // If the scene is paused, the user's adaptation level needs to remain
  1117.     // unchanged.
  1118.     g_bAdaptationInvalid = true;
  1119.  
  1120.     // Calculate the position of the lights in view space
  1121.     D3DXVECTOR4 avLightViewPosition[NUM_LIGHTS]; 
  1122.     for(int iLight=0; iLight < NUM_LIGHTS; iLight++)
  1123.     {
  1124.         D3DXMATRIX mView = *g_Camera.GetViewMatrix();
  1125.         D3DXVec4Transform(&avLightViewPosition[iLight], &g_avLightPosition[iLight], &mView);
  1126.     }
  1127.  
  1128.     // Set frame shader constants
  1129.     g_pEffect->SetBool("g_bEnableToneMap", g_bToneMap);
  1130.     g_pEffect->SetBool("g_bEnableBlueShift", g_bBlueShift);
  1131.     g_pEffect->SetValue("g_avLightPositionView", avLightViewPosition, sizeof(D3DXVECTOR4) * NUM_LIGHTS);
  1132.     g_pEffect->SetValue("g_avLightIntensity", g_avLightIntensity, sizeof(D3DXVECTOR4) * NUM_LIGHTS);
  1133.     
  1134. }
  1135.  
  1136.  
  1137. //--------------------------------------------------------------------------------------
  1138. // This callback function will be called at the end of every frame to perform all the 
  1139. // rendering calls for the scene, and it will also be called if the window needs to be 
  1140. // repainted. After this function has returned, the sample framework will call 
  1141. // IDirect3DDevice9::Present to display the contents of the next buffer in the swap chain
  1142. //--------------------------------------------------------------------------------------
  1143. void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  1144. {
  1145.     HRESULT hr;
  1146.      
  1147.     PDIRECT3DSURFACE9 pSurfLDR; // Low dynamic range surface for final output
  1148.     PDIRECT3DSURFACE9 pSurfHDR; // High dynamic range surface to store 
  1149.                                 // intermediate floating point color values
  1150.     
  1151.     // Setup HDR render target
  1152.     V( g_pd3dDevice->GetRenderTarget(0, &pSurfLDR) );
  1153.     V( g_pTexScene->GetSurfaceLevel(0, &pSurfHDR) );
  1154.     
  1155.     
  1156.     // Clear the viewport
  1157.     V( g_pd3dDevice->SetRenderTarget(0, pSurfHDR) );
  1158.     V( g_pd3dDevice->Clear(0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(0, 0, 0, 0), 1.0f, 0L) );
  1159.  
  1160.     // Render the scene
  1161.     if( SUCCEEDED( pd3dDevice->BeginScene() ) )
  1162.     {
  1163.         // Render the HDR Scene
  1164.         {
  1165.             CDXUTPerfEventGenerator g( DXUT_PERFEVENTCOLOR, L"Scene" );
  1166.             RenderScene();
  1167.         }
  1168.  
  1169.         // Create a scaled copy of the scene
  1170.         Scene_To_SceneScaled();
  1171.  
  1172.         // Setup tone mapping technique
  1173.         if( g_bToneMap )
  1174.             MeasureLuminance();
  1175.       
  1176.         // If FrameMove has been called, the user's adaptation level has also changed
  1177.         // and should be updated
  1178.         if( g_bAdaptationInvalid )
  1179.         {
  1180.             // Clear the update flag
  1181.             g_bAdaptationInvalid = false;
  1182.  
  1183.             // Calculate the current luminance adaptation level
  1184.             CalculateAdaptation();
  1185.         }
  1186.  
  1187.         // Now that luminance information has been gathered, the scene can be bright-pass filtered
  1188.         // to remove everything except bright lights and reflections.
  1189.         SceneScaled_To_BrightPass();
  1190.  
  1191.         // Blur the bright-pass filtered image to create the source texture for the star effect
  1192.         BrightPass_To_StarSource();
  1193.  
  1194.         // Scale-down the source texture for the star effect to create the source texture
  1195.         // for the bloom effect
  1196.         StarSource_To_BloomSource();
  1197.  
  1198.         // Render post-process lighting effects
  1199.         {
  1200.             CDXUTPerfEventGenerator g( DXUT_PERFEVENTCOLOR, L"Bloom" );
  1201.             RenderBloom();
  1202.         }
  1203.         {
  1204.             CDXUTPerfEventGenerator g( DXUT_PERFEVENTCOLOR, L"Star" );
  1205.             RenderStar();
  1206.         }
  1207.               
  1208.         // Draw the high dynamic range scene texture to the low dynamic range
  1209.         // back buffer. As part of this final pass, the scene will be tone-mapped
  1210.         // using the user's current adapted luminance, blue shift will occur
  1211.         // if the scene is determined to be very dark, and the post-process lighting
  1212.         // effect textures will be added to the scene.
  1213.         UINT uiPassCount, uiPass;
  1214.         
  1215.         V( g_pEffect->SetTechnique("FinalScenePass") );
  1216.         V( g_pEffect->SetFloat("g_fMiddleGray", g_fKeyValue) );
  1217.         
  1218.         V( g_pd3dDevice->SetRenderTarget(0, pSurfLDR) );
  1219.         V( g_pd3dDevice->SetTexture( 0, g_pTexScene ) );
  1220.         V( g_pd3dDevice->SetTexture( 1, g_apTexBloom[0] ) );
  1221.         V( g_pd3dDevice->SetTexture( 2, g_apTexStar[0] ) );
  1222.         V( g_pd3dDevice->SetTexture( 3, g_pTexAdaptedLuminanceCur ) );
  1223.         V( g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT ) );
  1224.         V( g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT ) );
  1225.         V( g_pd3dDevice->SetSamplerState( 1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR) );
  1226.         V( g_pd3dDevice->SetSamplerState( 1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ) );
  1227.         V( g_pd3dDevice->SetSamplerState( 2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR) );
  1228.         V( g_pd3dDevice->SetSamplerState( 2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ) );
  1229.         V( g_pd3dDevice->SetSamplerState( 3, D3DSAMP_MAGFILTER, D3DTEXF_POINT ) );
  1230.         V( g_pd3dDevice->SetSamplerState( 3, D3DSAMP_MINFILTER, D3DTEXF_POINT ) );
  1231.         
  1232.   
  1233.         V( g_pEffect->Begin(&uiPassCount, 0) );
  1234.         {
  1235.             CDXUTPerfEventGenerator g( DXUT_PERFEVENTCOLOR, L"Final Scene Pass" );
  1236.  
  1237.             for (uiPass = 0; uiPass < uiPassCount; uiPass++)
  1238.             {
  1239.                 V( g_pEffect->BeginPass(uiPass) );
  1240.                 
  1241.                 DrawFullScreenQuad( 0.0f, 0.0f, 1.0f, 1.0f );
  1242.                 
  1243.                 V( g_pEffect->EndPass() );
  1244.             }
  1245.         }
  1246.         V( g_pEffect->End() );
  1247.  
  1248.         {
  1249.             CDXUTPerfEventGenerator g( DXUT_PERFEVENTCOLOR, L"HUD / Stats" );
  1250.             RenderText();
  1251.             
  1252.             V( g_HUD.OnRender( fElapsedTime ) );
  1253.             V( g_SampleUI.OnRender( fElapsedTime ) );
  1254.         }
  1255.  
  1256.         V( pd3dDevice->EndScene() );
  1257.     }
  1258.  
  1259.     // Release surfaces
  1260.     SAFE_RELEASE(pSurfHDR);
  1261.     SAFE_RELEASE(pSurfLDR);
  1262. }
  1263.  
  1264.  
  1265. //-----------------------------------------------------------------------------
  1266. // Name: RenderScene()
  1267. // Desc: Render the world objects and lights
  1268. //-----------------------------------------------------------------------------
  1269. HRESULT RenderScene()
  1270. {
  1271.     HRESULT hr = S_OK;
  1272.  
  1273.     UINT uiPassCount, uiPass;
  1274.     D3DXMATRIXA16 mWorld;
  1275.     D3DXMATRIXA16 mTrans;
  1276.     D3DXMATRIXA16 mRotate;
  1277.     D3DXMATRIXA16 mObjectToView;
  1278.  
  1279.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP );
  1280.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP );
  1281.     
  1282.     D3DXMATRIX mView = *g_Camera.GetViewMatrix();
  1283.     
  1284.     g_pEffect->SetTechnique("RenderScene");
  1285.     g_pEffect->SetMatrix("g_mObjectToView", &mView);
  1286.     
  1287.     hr = g_pEffect->Begin(&uiPassCount, 0);
  1288.     if( FAILED(hr) )
  1289.         return hr;
  1290.  
  1291.     for (uiPass = 0; uiPass < uiPassCount; uiPass++)
  1292.     {
  1293.         g_pEffect->BeginPass(uiPass);
  1294.  
  1295.         // Turn off emissive lighting
  1296.         D3DXVECTOR4 vNull( 0.0f, 0.0f, 0.0f, 0.0f );
  1297.         g_pEffect->SetVector("g_vEmissive", &vNull); 
  1298.         
  1299.         // Enable texture
  1300.         g_pEffect->SetBool("g_bEnableTexture", true);
  1301.         g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
  1302.         g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
  1303.     
  1304.     
  1305.         // Render walls and columns
  1306.         g_pEffect->SetFloat("g_fPhongExponent", 5.0f);
  1307.         g_pEffect->SetFloat("g_fPhongCoefficient", 1.0f);
  1308.         g_pEffect->SetFloat("g_fDiffuseCoefficient", 0.5f);
  1309.         g_pd3dDevice->SetTexture(0, g_pTexWall );
  1310.         g_pEffect->CommitChanges();
  1311.         g_pWorldMesh->DrawSubset(0);
  1312.  
  1313.         // Render floor
  1314.         g_pEffect->SetFloat("g_fPhongExponent", 50.0f);
  1315.         g_pEffect->SetFloat("g_fPhongCoefficient", 3.0f);
  1316.         g_pEffect->SetFloat("g_fDiffuseCoefficient", 1.0f);
  1317.         g_pd3dDevice->SetTexture(0, g_pTexFloor );
  1318.         g_pEffect->CommitChanges();
  1319.         g_pWorldMesh->DrawSubset(1);
  1320.  
  1321.         // Render ceiling
  1322.         g_pEffect->SetFloat("g_fPhongExponent", 5.0f);
  1323.         g_pEffect->SetFloat("g_fPhongCoefficient", 0.3f);
  1324.         g_pEffect->SetFloat("g_fDiffuseCoefficient", 0.3f);
  1325.         g_pd3dDevice->SetTexture(0, g_pTexCeiling );
  1326.         g_pEffect->CommitChanges();
  1327.         g_pWorldMesh->DrawSubset(2);
  1328.  
  1329.         // Render paintings
  1330.         g_pEffect->SetFloat("g_fPhongExponent", 5.0f);
  1331.         g_pEffect->SetFloat("g_fPhongCoefficient", 0.3f);
  1332.         g_pEffect->SetFloat("g_fDiffuseCoefficient", 1.0f);
  1333.         g_pd3dDevice->SetTexture(0, g_pTexPainting );
  1334.         g_pEffect->CommitChanges();
  1335.         g_pWorldMesh->DrawSubset(3);
  1336.  
  1337.         // Draw the light spheres.
  1338.         g_pEffect->SetFloat("g_fPhongExponent", 5.0f);
  1339.         g_pEffect->SetFloat("g_fPhongCoefficient", 1.0f);
  1340.         g_pEffect->SetFloat("g_fDiffuseCoefficient", 1.0f);
  1341.         g_pEffect->SetBool("g_bEnableTexture", false);
  1342.         
  1343.         for(int iLight=0; iLight < NUM_LIGHTS; iLight++)
  1344.         {  
  1345.             // Just position the point light -- no need to orient it
  1346.             D3DXMATRIXA16 mScale;
  1347.             D3DXMatrixScaling( &mScale, 0.05f, 0.05f, 0.05f );
  1348.             
  1349.             mView = *g_Camera.GetViewMatrix();
  1350.             D3DXMatrixTranslation(&mWorld, g_avLightPosition[iLight].x, g_avLightPosition[iLight].y, g_avLightPosition[iLight].z);
  1351.             mWorld = mScale * mWorld;
  1352.             mObjectToView = mWorld * mView;
  1353.             g_pEffect->SetMatrix("g_mObjectToView", &mObjectToView);
  1354.  
  1355.             // A light which illuminates objects at 80 lum/sr should be drawn
  1356.             // at 3183 lumens/meter^2/steradian, which equates to a multiplier
  1357.             // of 39.78 per lumen.
  1358.             D3DXVECTOR4 vEmissive = EMISSIVE_COEFFICIENT * g_avLightIntensity[iLight];
  1359.             g_pEffect->SetVector("g_vEmissive", &vEmissive );    
  1360.     
  1361.             g_pEffect->CommitChanges();
  1362.             g_pmeshSphere->DrawSubset(0);
  1363.         }
  1364.         g_pEffect->EndPass();
  1365.     }
  1366.  
  1367.     g_pEffect->End();
  1368.  
  1369.     return S_OK;
  1370. }
  1371.  
  1372.  
  1373.  
  1374.  
  1375. //-----------------------------------------------------------------------------
  1376. // Name: MeasureLuminance()
  1377. // Desc: Measure the average log luminance in the scene.
  1378. //-----------------------------------------------------------------------------
  1379. HRESULT MeasureLuminance()
  1380. {
  1381.     HRESULT hr = S_OK;
  1382.     UINT uiPassCount, uiPass;
  1383.     int i, x, y, index;
  1384.     D3DXVECTOR2 avSampleOffsets[MAX_SAMPLES];
  1385.  
  1386.     
  1387.     DWORD dwCurTexture = NUM_TONEMAP_TEXTURES-1;
  1388.  
  1389.     // Sample log average luminance
  1390.     PDIRECT3DSURFACE9 apSurfToneMap[NUM_TONEMAP_TEXTURES] = {0};
  1391.  
  1392.     // Retrieve the tonemap surfaces
  1393.     for( i=0; i < NUM_TONEMAP_TEXTURES; i++ )
  1394.     {
  1395.         hr = g_apTexToneMap[i]->GetSurfaceLevel( 0, &apSurfToneMap[i] );
  1396.         if( FAILED(hr) )
  1397.             goto LCleanReturn;
  1398.     }
  1399.  
  1400.     D3DSURFACE_DESC desc;
  1401.     g_apTexToneMap[dwCurTexture]->GetLevelDesc( 0, &desc );
  1402.  
  1403.     
  1404.     // Initialize the sample offsets for the initial luminance pass.
  1405.     float tU, tV;
  1406.     tU = 1.0f / (3.0f * desc.Width);
  1407.     tV = 1.0f / (3.0f * desc.Height);
  1408.     
  1409.     index=0;
  1410.     for( x = -1; x <= 1; x++ )
  1411.     {
  1412.         for( y = -1; y <= 1; y++ )
  1413.         {
  1414.             avSampleOffsets[index].x = x * tU;
  1415.             avSampleOffsets[index].y = y * tV;
  1416.  
  1417.             index++;
  1418.         }
  1419.     }
  1420.  
  1421.     
  1422.     // After this pass, the g_apTexToneMap[NUM_TONEMAP_TEXTURES-1] texture will contain
  1423.     // a scaled, grayscale copy of the HDR scene. Individual texels contain the log 
  1424.     // of average luminance values for points sampled on the HDR texture.
  1425.     g_pEffect->SetTechnique("SampleAvgLum");
  1426.     g_pEffect->SetValue("g_avSampleOffsets", avSampleOffsets, sizeof(avSampleOffsets));
  1427.     
  1428.     g_pd3dDevice->SetRenderTarget(0, apSurfToneMap[dwCurTexture]);
  1429.     g_pd3dDevice->SetTexture(0, g_pTexSceneScaled);
  1430.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
  1431.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
  1432.     g_pd3dDevice->SetSamplerState( 1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
  1433.     g_pd3dDevice->SetSamplerState( 1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
  1434.     
  1435.     
  1436.     hr = g_pEffect->Begin(&uiPassCount, 0);
  1437.     if( FAILED(hr) )
  1438.         goto LCleanReturn;
  1439.  
  1440.     for (uiPass = 0; uiPass < uiPassCount; uiPass++)
  1441.     {
  1442.         g_pEffect->BeginPass(uiPass);
  1443.  
  1444.         // Draw a fullscreen quad to sample the RT
  1445.         DrawFullScreenQuad(0.0f, 0.0f, 1.0f, 1.0f);
  1446.  
  1447.         g_pEffect->EndPass();
  1448.     }
  1449.  
  1450.     g_pEffect->End();
  1451.     dwCurTexture--;
  1452.     
  1453.     // Initialize the sample offsets for the iterative luminance passes
  1454.     while( dwCurTexture > 0 )
  1455.     {
  1456.         g_apTexToneMap[dwCurTexture+1]->GetLevelDesc( 0, &desc );
  1457.         GetSampleOffsets_DownScale4x4( desc.Width, desc.Height, avSampleOffsets );
  1458.     
  1459.  
  1460.         // Each of these passes continue to scale down the log of average
  1461.         // luminance texture created above, storing intermediate results in 
  1462.         // g_apTexToneMap[1] through g_apTexToneMap[NUM_TONEMAP_TEXTURES-1].
  1463.         g_pEffect->SetTechnique("ResampleAvgLum");
  1464.         g_pEffect->SetValue("g_avSampleOffsets", avSampleOffsets, sizeof(avSampleOffsets));
  1465.  
  1466.         g_pd3dDevice->SetRenderTarget(0, apSurfToneMap[dwCurTexture]);
  1467.         g_pd3dDevice->SetTexture(0, g_apTexToneMap[dwCurTexture+1]);
  1468.         g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
  1469.         g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT );
  1470.     
  1471.         
  1472.         hr = g_pEffect->Begin(&uiPassCount, 0);
  1473.         if( FAILED(hr) )
  1474.             goto LCleanReturn;
  1475.         
  1476.         for (uiPass = 0; uiPass < uiPassCount; uiPass++)
  1477.         {
  1478.             g_pEffect->BeginPass(uiPass);
  1479.  
  1480.             // Draw a fullscreen quad to sample the RT
  1481.             DrawFullScreenQuad(0.0f, 0.0f, 1.0f, 1.0f);
  1482.  
  1483.             g_pEffect->EndPass();
  1484.         }
  1485.  
  1486.         g_pEffect->End();
  1487.         dwCurTexture--;
  1488.     }
  1489.  
  1490.     // Downsample to 1x1
  1491.     g_apTexToneMap[1]->GetLevelDesc( 0, &desc );
  1492.     GetSampleOffsets_DownScale4x4( desc.Width, desc.Height, avSampleOffsets );
  1493.     
  1494.  
  1495.     // Perform the final pass of the average luminance calculation. This pass
  1496.     // scales the 4x4 log of average luminance texture from above and performs
  1497.     // an exp() operation to return a single texel cooresponding to the average
  1498.     // luminance of the scene in g_apTexToneMap[0].
  1499.     g_pEffect->SetTechnique("ResampleAvgLumExp");
  1500.     g_pEffect->SetValue("g_avSampleOffsets", avSampleOffsets, sizeof(avSampleOffsets));
  1501.     
  1502.     g_pd3dDevice->SetRenderTarget(0, apSurfToneMap[0]);
  1503.     g_pd3dDevice->SetTexture(0, g_apTexToneMap[1]);
  1504.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
  1505.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT );
  1506.     
  1507.      
  1508.     hr = g_pEffect->Begin(&uiPassCount, 0);
  1509.     if( FAILED(hr) )
  1510.         goto LCleanReturn;
  1511.  
  1512.     for (uiPass = 0; uiPass < uiPassCount; uiPass++)
  1513.     {
  1514.         g_pEffect->BeginPass(uiPass);
  1515.  
  1516.         // Draw a fullscreen quad to sample the RT
  1517.         DrawFullScreenQuad(0.0f, 0.0f, 1.0f, 1.0f);
  1518.  
  1519.         g_pEffect->EndPass();
  1520.     }
  1521.  
  1522.     g_pEffect->End();
  1523.  
  1524.  
  1525.     hr = S_OK;
  1526. LCleanReturn:
  1527.     for( i=0; i < NUM_TONEMAP_TEXTURES; i++ )
  1528.     {
  1529.         SAFE_RELEASE( apSurfToneMap[i] );
  1530.     }
  1531.  
  1532.     return hr;
  1533. }
  1534.  
  1535.  
  1536.  
  1537.  
  1538. //-----------------------------------------------------------------------------
  1539. // Name: CalculateAdaptation()
  1540. // Desc: Increment the user's adapted luminance
  1541. //-----------------------------------------------------------------------------
  1542. HRESULT CalculateAdaptation()
  1543. {
  1544.     HRESULT hr = S_OK;
  1545.     UINT uiPass, uiPassCount;
  1546.  
  1547.     // Swap current & last luminance
  1548.     PDIRECT3DTEXTURE9 pTexSwap = g_pTexAdaptedLuminanceLast;
  1549.     g_pTexAdaptedLuminanceLast = g_pTexAdaptedLuminanceCur;
  1550.     g_pTexAdaptedLuminanceCur = pTexSwap;
  1551.     
  1552.     PDIRECT3DSURFACE9 pSurfAdaptedLum = NULL;
  1553.     hr = g_pTexAdaptedLuminanceCur->GetSurfaceLevel(0, &pSurfAdaptedLum);
  1554.     if( FAILED(hr) )
  1555.         return hr;
  1556.  
  1557.     // This simulates the light adaptation that occurs when moving from a 
  1558.     // dark area to a bright area, or vice versa. The g_pTexAdaptedLuminance
  1559.     // texture stores a single texel cooresponding to the user's adapted 
  1560.     // level.
  1561.     g_pEffect->SetTechnique("CalculateAdaptedLum");
  1562.     g_pEffect->SetFloat("g_fElapsedTime", DXUTGetElapsedTime());
  1563.     
  1564.     g_pd3dDevice->SetRenderTarget(0, pSurfAdaptedLum);
  1565.     g_pd3dDevice->SetTexture(0, g_pTexAdaptedLuminanceLast);
  1566.     g_pd3dDevice->SetTexture(1, g_apTexToneMap[0]);
  1567.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
  1568.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT );
  1569.     g_pd3dDevice->SetSamplerState( 1, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
  1570.     g_pd3dDevice->SetSamplerState( 1, D3DSAMP_MINFILTER, D3DTEXF_POINT );
  1571.  
  1572.     
  1573.     hr = g_pEffect->Begin(&uiPassCount, 0);
  1574.     if( FAILED(hr) )
  1575.         return hr;
  1576.     
  1577.     for (uiPass = 0; uiPass < uiPassCount; uiPass++)
  1578.     {
  1579.         g_pEffect->BeginPass(uiPass);
  1580.  
  1581.         // Draw a fullscreen quad to sample the RT
  1582.         DrawFullScreenQuad(0.0f, 0.0f, 1.0f, 1.0f);
  1583.  
  1584.         g_pEffect->EndPass();
  1585.     }
  1586.     
  1587.     g_pEffect->End();
  1588.  
  1589.  
  1590.     SAFE_RELEASE( pSurfAdaptedLum );
  1591.     return S_OK;
  1592. }
  1593.  
  1594.  
  1595.  
  1596.  
  1597. //-----------------------------------------------------------------------------
  1598. // Name: RenderStar()
  1599. // Desc: Render the blooming effect
  1600. //-----------------------------------------------------------------------------
  1601. HRESULT RenderStar()
  1602. {
  1603.     HRESULT hr = S_OK;
  1604.     UINT uiPassCount, uiPass;
  1605.     int i, d, p, s; // Loop variables
  1606.  
  1607.     LPDIRECT3DSURFACE9 pSurfStar = NULL;
  1608.     hr = g_apTexStar[0]->GetSurfaceLevel( 0, &pSurfStar );
  1609.     if( FAILED(hr) )
  1610.         return hr;
  1611.  
  1612.     // Clear the star texture
  1613.     g_pd3dDevice->ColorFill( pSurfStar, NULL, D3DCOLOR_ARGB(0, 0, 0, 0) );
  1614.     SAFE_RELEASE( pSurfStar );
  1615.  
  1616.     // Avoid rendering the star if it's not being used in the current glare
  1617.     if( g_GlareDef.m_fGlareLuminance <= 0.0f ||
  1618.         g_GlareDef.m_fStarLuminance <= 0.0f )
  1619.     {
  1620.         return S_OK ;
  1621.     }
  1622.  
  1623.     // Initialize the constants used during the effect
  1624.     const CStarDef& starDef = g_GlareDef.m_starDef ;
  1625.     const float fTanFoV = atanf(D3DX_PI/8) ;
  1626.     const D3DXVECTOR4 vWhite( 1.0f, 1.0f, 1.0f, 1.0f );
  1627.     static const s_maxPasses = 3 ;
  1628.     static const int nSamples = 8 ;
  1629.     static D3DXVECTOR4 s_aaColor[s_maxPasses][8] ;
  1630.     static const D3DXCOLOR s_colorWhite(0.63f, 0.63f, 0.63f, 0.0f) ;
  1631.     
  1632.     D3DXVECTOR4 avSampleWeights[MAX_SAMPLES];
  1633.     D3DXVECTOR2 avSampleOffsets[MAX_SAMPLES];
  1634.         
  1635.     g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE) ;
  1636.     g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE) ;
  1637.  
  1638.     PDIRECT3DSURFACE9 pSurfSource = NULL;
  1639.     PDIRECT3DSURFACE9 pSurfDest = NULL;
  1640.  
  1641.     // Set aside all the star texture surfaces as a convenience
  1642.     PDIRECT3DSURFACE9 apSurfStar[NUM_STAR_TEXTURES] = {0};
  1643.     for( i=0; i < NUM_STAR_TEXTURES; i++ )
  1644.     {
  1645.         hr = g_apTexStar[i]->GetSurfaceLevel( 0, &apSurfStar[i] );
  1646.         if( FAILED(hr) )
  1647.             goto LCleanReturn;
  1648.     }
  1649.  
  1650.     // Get the source texture dimensions
  1651.     hr = g_pTexStarSource->GetSurfaceLevel( 0, &pSurfSource );
  1652.     if( FAILED(hr) )
  1653.         goto LCleanReturn;
  1654.  
  1655.     D3DSURFACE_DESC desc;
  1656.     hr = pSurfSource->GetDesc( &desc );
  1657.     if( FAILED(hr) )
  1658.         goto LCleanReturn;
  1659.  
  1660.     SAFE_RELEASE( pSurfSource );
  1661.  
  1662.     float srcW;
  1663.     srcW = (FLOAT) desc.Width;
  1664.     float srcH;
  1665.     srcH= (FLOAT) desc.Height;
  1666.  
  1667.     
  1668.    
  1669.     for (p = 0 ; p < s_maxPasses ; p ++)
  1670.     {
  1671.         float ratio;
  1672.         ratio = (float)(p + 1) / (float)s_maxPasses ;
  1673.         
  1674.         for (s = 0 ; s < nSamples ; s ++)
  1675.         {
  1676.             D3DXCOLOR chromaticAberrColor ;
  1677.             D3DXColorLerp(&chromaticAberrColor,
  1678.                 &( CStarDef::GetChromaticAberrationColor(s) ),
  1679.                 &s_colorWhite,
  1680.                 ratio) ;
  1681.  
  1682.             D3DXColorLerp( (D3DXCOLOR*)&( s_aaColor[p][s] ),
  1683.                 &s_colorWhite, &chromaticAberrColor,
  1684.                 g_GlareDef.m_fChromaticAberration ) ;
  1685.         }
  1686.     }
  1687.  
  1688.     float radOffset;
  1689.     radOffset = g_GlareDef.m_fStarInclination + starDef.m_fInclination ;
  1690.     
  1691.  
  1692.     PDIRECT3DTEXTURE9 pTexSource;
  1693.  
  1694.  
  1695.     // Direction loop
  1696.     for (d = 0 ; d < starDef.m_nStarLines ; d ++)
  1697.     {
  1698.         CONST STARLINE& starLine = starDef.m_pStarLine[d] ;
  1699.  
  1700.         pTexSource = g_pTexStarSource;
  1701.         
  1702.         float rad;
  1703.         rad = radOffset + starLine.fInclination ;
  1704.         float sn, cs;
  1705.         sn = sinf(rad), cs = cosf(rad) ;
  1706.         D3DXVECTOR2 vtStepUV;
  1707.         vtStepUV.x = sn / srcW * starLine.fSampleLength ;
  1708.         vtStepUV.y = cs / srcH * starLine.fSampleLength ;
  1709.         
  1710.         float attnPowScale;
  1711.         attnPowScale = (fTanFoV + 0.1f) * 1.0f *
  1712.                        (160.0f + 120.0f) / (srcW + srcH) * 1.2f ;
  1713.  
  1714.         // 1 direction expansion loop
  1715.         g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE) ;
  1716.         
  1717.         int iWorkTexture;
  1718.         iWorkTexture = 1 ;
  1719.         for (p = 0 ; p < starLine.nPasses ; p ++)
  1720.         {
  1721.             
  1722.             if (p == starLine.nPasses - 1)
  1723.             {
  1724.                 // Last pass move to other work buffer
  1725.                 pSurfDest = apSurfStar[d+4];
  1726.             }
  1727.             else {
  1728.                 pSurfDest = apSurfStar[iWorkTexture];
  1729.             }
  1730.  
  1731.             // Sampling configration for each stage
  1732.             for (i = 0 ; i < nSamples ; i ++)
  1733.             {
  1734.                 float lum;
  1735.                 lum = powf( starLine.fAttenuation, attnPowScale * i );
  1736.                 
  1737.                 avSampleWeights[i] = s_aaColor[starLine.nPasses - 1 - p][i] *
  1738.                                 lum * (p+1.0f) * 0.5f ;
  1739.                                 
  1740.                 
  1741.                 // Offset of sampling coordinate
  1742.                 avSampleOffsets[i].x = vtStepUV.x * i ;
  1743.                 avSampleOffsets[i].y = vtStepUV.y * i ;
  1744.                 if ( fabs(avSampleOffsets[i].x) >= 0.9f ||
  1745.                      fabs(avSampleOffsets[i].y) >= 0.9f )
  1746.                 {
  1747.                     avSampleOffsets[i].x = 0.0f ;
  1748.                     avSampleOffsets[i].y = 0.0f ;
  1749.                     avSampleWeights[i] *= 0.0f ;
  1750.                 }
  1751.                 
  1752.             }
  1753.  
  1754.             
  1755.             g_pEffect->SetTechnique("Star");
  1756.             g_pEffect->SetValue("g_avSampleOffsets", avSampleOffsets, sizeof(avSampleOffsets));
  1757.             g_pEffect->SetVectorArray("g_avSampleWeights", avSampleWeights, nSamples);
  1758.             
  1759.             g_pd3dDevice->SetRenderTarget( 0, pSurfDest );
  1760.             g_pd3dDevice->SetTexture( 0, pTexSource );
  1761.             g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
  1762.             g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
  1763.     
  1764.             
  1765.             hr = g_pEffect->Begin(&uiPassCount, 0);
  1766.             if( FAILED(hr) )
  1767.                 return hr;
  1768.             
  1769.             for (uiPass = 0; uiPass < uiPassCount; uiPass++)
  1770.             {
  1771.                 g_pEffect->BeginPass(uiPass);
  1772.  
  1773.                 // Draw a fullscreen quad to sample the RT
  1774.                 DrawFullScreenQuad(0.0f, 0.0f, 1.0f, 1.0f);
  1775.  
  1776.                 g_pEffect->EndPass();
  1777.             }
  1778.             
  1779.             g_pEffect->End();
  1780.  
  1781.             // Setup next expansion
  1782.             vtStepUV *= nSamples ;
  1783.             attnPowScale *= nSamples ;
  1784.  
  1785.             // Set the work drawn just before to next texture source.
  1786.             pTexSource = g_apTexStar[iWorkTexture];
  1787.  
  1788.             iWorkTexture += 1 ;
  1789.             if (iWorkTexture > 2) {
  1790.                 iWorkTexture = 1 ;
  1791.             }
  1792.  
  1793.         }
  1794.     }
  1795.  
  1796.  
  1797.     pSurfDest = apSurfStar[0];
  1798.  
  1799.     
  1800.     for( i=0; i < starDef.m_nStarLines; i++ )
  1801.     {
  1802.         g_pd3dDevice->SetTexture( i, g_apTexStar[i+4] );
  1803.         g_pd3dDevice->SetSamplerState( i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
  1804.         g_pd3dDevice->SetSamplerState( i, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
  1805.  
  1806.         avSampleWeights[i] = vWhite * 1.0f / (FLOAT) starDef.m_nStarLines;
  1807.     }
  1808.  
  1809.     CHAR strTechnique[256];
  1810.     _snprintf( strTechnique, 256, "MergeTextures_%d", starDef.m_nStarLines );
  1811.     strTechnique[255] = 0;
  1812.  
  1813.     g_pEffect->SetTechnique(strTechnique);
  1814.  
  1815.     g_pEffect->SetVectorArray("g_avSampleWeights", avSampleWeights, starDef.m_nStarLines);
  1816.     
  1817.     g_pd3dDevice->SetRenderTarget( 0, pSurfDest );
  1818.     
  1819.     hr = g_pEffect->Begin(&uiPassCount, 0);
  1820.     if( FAILED(hr) )
  1821.         goto LCleanReturn;
  1822.     
  1823.     for (uiPass = 0; uiPass < uiPassCount; uiPass++)
  1824.     {
  1825.         g_pEffect->BeginPass(uiPass);
  1826.  
  1827.         // Draw a fullscreen quad to sample the RT
  1828.         DrawFullScreenQuad(0.0f, 0.0f, 1.0f, 1.0f);
  1829.  
  1830.         g_pEffect->EndPass();
  1831.     }
  1832.     
  1833.     g_pEffect->End();
  1834.  
  1835.     
  1836.     hr = S_OK;
  1837. LCleanReturn:
  1838.     for( i=0; i < NUM_STAR_TEXTURES; i++ )
  1839.     {
  1840.         SAFE_RELEASE( apSurfStar[i] );
  1841.     }
  1842.  
  1843.     return hr;
  1844. }
  1845.  
  1846.  
  1847.  
  1848.  
  1849. //-----------------------------------------------------------------------------
  1850. // Name: RenderBloom()
  1851. // Desc: Render the blooming effect
  1852. //-----------------------------------------------------------------------------
  1853. HRESULT RenderBloom()
  1854. {
  1855.     HRESULT hr = S_OK;
  1856.     UINT uiPassCount, uiPass;
  1857.     int i=0;
  1858.  
  1859.  
  1860.     D3DXVECTOR2 avSampleOffsets[MAX_SAMPLES];
  1861.     FLOAT       afSampleOffsets[MAX_SAMPLES];
  1862.     D3DXVECTOR4 avSampleWeights[MAX_SAMPLES];
  1863.  
  1864.     PDIRECT3DSURFACE9 pSurfScaledHDR;
  1865.     g_pTexSceneScaled->GetSurfaceLevel(0, &pSurfScaledHDR);
  1866.  
  1867.     PDIRECT3DSURFACE9 pSurfBloom;
  1868.     g_apTexBloom[0]->GetSurfaceLevel(0, &pSurfBloom);
  1869.  
  1870.     PDIRECT3DSURFACE9 pSurfHDR;
  1871.     g_pTexScene->GetSurfaceLevel(0, &pSurfHDR);  
  1872.     
  1873.     PDIRECT3DSURFACE9 pSurfTempBloom;
  1874.     g_apTexBloom[1]->GetSurfaceLevel(0, &pSurfTempBloom);
  1875.  
  1876.     PDIRECT3DSURFACE9 pSurfBloomSource;
  1877.     g_apTexBloom[2]->GetSurfaceLevel(0, &pSurfBloomSource);
  1878.  
  1879.     // Clear the bloom texture
  1880.     g_pd3dDevice->ColorFill( pSurfBloom, NULL, D3DCOLOR_ARGB(0, 0, 0, 0) );
  1881.  
  1882.     if (g_GlareDef.m_fGlareLuminance <= 0.0f ||
  1883.         g_GlareDef.m_fBloomLuminance <= 0.0f)
  1884.     {
  1885.         hr = S_OK;
  1886.         goto LCleanReturn;
  1887.     }
  1888.  
  1889.     if( g_GlareDef.m_fGlareLuminance <= 0.0f ||
  1890.         g_GlareDef.m_fBloomLuminance <= 0.0f )
  1891.     {
  1892.         return S_OK ;
  1893.     }
  1894.  
  1895.     RECT rectSrc;
  1896.     GetTextureRect( g_pTexBloomSource, &rectSrc );
  1897.     InflateRect( &rectSrc, -1, -1 );
  1898.  
  1899.     RECT rectDest;
  1900.     GetTextureRect( g_apTexBloom[2], &rectDest );
  1901.     InflateRect( &rectDest, -1, -1 );
  1902.  
  1903.     CoordRect coords;
  1904.     GetTextureCoords( g_pTexBloomSource, &rectSrc, g_apTexBloom[2], &rectDest, &coords );
  1905.    
  1906.     D3DSURFACE_DESC desc;
  1907.     hr = g_pTexBloomSource->GetLevelDesc( 0, &desc );
  1908.     if( FAILED(hr) )
  1909.         return hr;
  1910.  
  1911.  
  1912.     g_pEffect->SetTechnique("GaussBlur5x5");
  1913.  
  1914.     hr = GetSampleOffsets_GaussBlur5x5( desc.Width, desc.Height, avSampleOffsets, avSampleWeights, 1.0f );
  1915.  
  1916.     g_pEffect->SetValue("g_avSampleOffsets", avSampleOffsets, sizeof(avSampleOffsets));
  1917.     g_pEffect->SetValue("g_avSampleWeights", avSampleWeights, sizeof(avSampleWeights));
  1918.    
  1919.     g_pd3dDevice->SetRenderTarget(0, pSurfBloomSource );
  1920.     g_pd3dDevice->SetTexture( 0, g_pTexBloomSource );
  1921.     g_pd3dDevice->SetScissorRect( &rectDest );
  1922.     g_pd3dDevice->SetRenderState( D3DRS_SCISSORTESTENABLE, TRUE );
  1923.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT );
  1924.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
  1925.        
  1926.     
  1927.     hr = g_pEffect->Begin(&uiPassCount, 0);
  1928.     if( FAILED(hr) )
  1929.         goto LCleanReturn;
  1930.     
  1931.     for (uiPass = 0; uiPass < uiPassCount; uiPass++)
  1932.     {
  1933.         g_pEffect->BeginPass(uiPass);
  1934.  
  1935.         // Draw a fullscreen quad to sample the RT
  1936.         DrawFullScreenQuad( coords );
  1937.  
  1938.         g_pEffect->EndPass();
  1939.     }
  1940.     g_pEffect->End();
  1941.     g_pd3dDevice->SetRenderState( D3DRS_SCISSORTESTENABLE, FALSE );
  1942.  
  1943.     hr = g_apTexBloom[2]->GetLevelDesc( 0, &desc );
  1944.     if( FAILED(hr) )
  1945.         return hr;
  1946.  
  1947.     hr = GetSampleOffsets_Bloom( desc.Width, afSampleOffsets, avSampleWeights, 3.0f, 2.0f );
  1948.     for( i=0; i < MAX_SAMPLES; i++ )
  1949.     {
  1950.         avSampleOffsets[i] = D3DXVECTOR2( afSampleOffsets[i], 0.0f );
  1951.     }
  1952.      
  1953.  
  1954.     g_pEffect->SetTechnique("Bloom");
  1955.     g_pEffect->SetValue("g_avSampleOffsets", avSampleOffsets, sizeof(avSampleOffsets));
  1956.     g_pEffect->SetValue("g_avSampleWeights", avSampleWeights, sizeof(avSampleWeights));
  1957.    
  1958.     g_pd3dDevice->SetRenderTarget(0, pSurfTempBloom);
  1959.     g_pd3dDevice->SetTexture( 0, g_apTexBloom[2] );
  1960.     g_pd3dDevice->SetScissorRect( &rectDest );
  1961.     g_pd3dDevice->SetRenderState( D3DRS_SCISSORTESTENABLE, TRUE );
  1962.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT );
  1963.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
  1964.        
  1965.     
  1966.     g_pEffect->Begin(&uiPassCount, 0);
  1967.     for (uiPass = 0; uiPass < uiPassCount; uiPass++)
  1968.     {
  1969.         g_pEffect->BeginPass(uiPass);
  1970.  
  1971.         // Draw a fullscreen quad to sample the RT
  1972.         DrawFullScreenQuad( coords );
  1973.  
  1974.         g_pEffect->EndPass();
  1975.     }
  1976.     g_pEffect->End();
  1977.     g_pd3dDevice->SetRenderState( D3DRS_SCISSORTESTENABLE, FALSE );
  1978.     
  1979.  
  1980.     hr = g_apTexBloom[1]->GetLevelDesc( 0, &desc );
  1981.     if( FAILED(hr) )
  1982.         return hr;
  1983.  
  1984.     hr = GetSampleOffsets_Bloom( desc.Height, afSampleOffsets, avSampleWeights, 3.0f, 2.0f );
  1985.     for( i=0; i < MAX_SAMPLES; i++ )
  1986.     {
  1987.         avSampleOffsets[i] = D3DXVECTOR2( 0.0f, afSampleOffsets[i] );
  1988.     }
  1989.  
  1990.     
  1991.     GetTextureRect( g_apTexBloom[1], &rectSrc );
  1992.     InflateRect( &rectSrc, -1, -1 );
  1993.  
  1994.     GetTextureCoords( g_apTexBloom[1], &rectSrc, g_apTexBloom[0], NULL, &coords );
  1995.  
  1996.     
  1997.     g_pEffect->SetTechnique("Bloom");
  1998.     g_pEffect->SetValue("g_avSampleOffsets", avSampleOffsets, sizeof(avSampleOffsets));
  1999.     g_pEffect->SetValue("g_avSampleWeights", avSampleWeights, sizeof(avSampleWeights));
  2000.     
  2001.     g_pd3dDevice->SetRenderTarget(0, pSurfBloom);
  2002.     g_pd3dDevice->SetTexture(0, g_apTexBloom[1]);
  2003.    g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT );
  2004.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
  2005.        
  2006.    
  2007.     hr = g_pEffect->Begin(&uiPassCount, 0);
  2008.     if( FAILED(hr) )
  2009.         goto LCleanReturn;
  2010.  
  2011.     for (uiPass = 0; uiPass < uiPassCount; uiPass++)
  2012.     {
  2013.         g_pEffect->BeginPass(uiPass);
  2014.  
  2015.         // Draw a fullscreen quad to sample the RT
  2016.         DrawFullScreenQuad( coords );
  2017.  
  2018.         g_pEffect->EndPass();
  2019.     }
  2020.  
  2021.     g_pEffect->End();
  2022.    
  2023.   
  2024.     hr = S_OK;
  2025.  
  2026. LCleanReturn:
  2027.     SAFE_RELEASE( pSurfBloomSource );
  2028.     SAFE_RELEASE( pSurfTempBloom );
  2029.     SAFE_RELEASE( pSurfBloom );
  2030.     SAFE_RELEASE( pSurfHDR );
  2031.     SAFE_RELEASE( pSurfScaledHDR );
  2032.     
  2033.     return hr;
  2034. }
  2035.  
  2036.  
  2037.  
  2038. //-----------------------------------------------------------------------------
  2039. // Name: DrawFullScreenQuad
  2040. // Desc: Draw a properly aligned quad covering the entire render target
  2041. //-----------------------------------------------------------------------------
  2042. void DrawFullScreenQuad(float fLeftU, float fTopV, float fRightU, float fBottomV)
  2043. {
  2044.     D3DSURFACE_DESC dtdsdRT;
  2045.     PDIRECT3DSURFACE9 pSurfRT;
  2046.  
  2047.     // Acquire render target width and height
  2048.     g_pd3dDevice->GetRenderTarget(0, &pSurfRT);
  2049.     pSurfRT->GetDesc(&dtdsdRT);
  2050.     pSurfRT->Release();
  2051.  
  2052.     // Ensure that we're directly mapping texels to pixels by offset by 0.5
  2053.     // For more info see the doc page titled "Directly Mapping Texels to Pixels"
  2054.     FLOAT fWidth5 = (FLOAT)dtdsdRT.Width - 0.5f;
  2055.     FLOAT fHeight5 = (FLOAT)dtdsdRT.Height - 0.5f;
  2056.  
  2057.     // Draw the quad
  2058.     ScreenVertex svQuad[4];
  2059.  
  2060.     svQuad[0].p = D3DXVECTOR4(-0.5f, -0.5f, 0.5f, 1.0f);
  2061.     svQuad[0].t = D3DXVECTOR2(fLeftU, fTopV);
  2062.  
  2063.     svQuad[1].p = D3DXVECTOR4(fWidth5, -0.5f, 0.5f, 1.0f);
  2064.     svQuad[1].t = D3DXVECTOR2(fRightU, fTopV);
  2065.  
  2066.     svQuad[2].p = D3DXVECTOR4(-0.5f, fHeight5, 0.5f, 1.0f);
  2067.     svQuad[2].t = D3DXVECTOR2(fLeftU, fBottomV);
  2068.  
  2069.     svQuad[3].p = D3DXVECTOR4(fWidth5, fHeight5, 0.5f, 1.0f);
  2070.     svQuad[3].t = D3DXVECTOR2(fRightU, fBottomV);
  2071.  
  2072.     g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
  2073.     g_pd3dDevice->SetFVF(ScreenVertex::FVF);
  2074.     g_pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, svQuad, sizeof(ScreenVertex));
  2075.     g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
  2076. }
  2077.  
  2078.  
  2079. //-----------------------------------------------------------------------------
  2080. // Name: GetTextureRect()
  2081. // Desc: Get the dimensions of the texture
  2082. //-----------------------------------------------------------------------------
  2083. HRESULT GetTextureRect( PDIRECT3DTEXTURE9 pTexture, RECT* pRect )
  2084. {
  2085.     HRESULT hr = S_OK;
  2086.  
  2087.     if( pTexture == NULL || pRect == NULL )
  2088.         return E_INVALIDARG;
  2089.  
  2090.     D3DSURFACE_DESC desc;
  2091.     hr = pTexture->GetLevelDesc( 0, &desc );
  2092.     if( FAILED(hr) )
  2093.         return hr;
  2094.  
  2095.     pRect->left = 0;
  2096.     pRect->top = 0;
  2097.     pRect->right = desc.Width;
  2098.     pRect->bottom = desc.Height;
  2099.  
  2100.     return S_OK;
  2101. }
  2102.  
  2103.  
  2104.  
  2105.  
  2106. //-----------------------------------------------------------------------------
  2107. // Name: GetTextureCoords()
  2108. // Desc: Get the texture coordinates to use when rendering into the destination
  2109. //       texture, given the source and destination rectangles
  2110. //-----------------------------------------------------------------------------
  2111. HRESULT GetTextureCoords( PDIRECT3DTEXTURE9 pTexSrc, RECT* pRectSrc, 
  2112.                           PDIRECT3DTEXTURE9 pTexDest, RECT* pRectDest, CoordRect* pCoords )
  2113. {
  2114.     HRESULT hr = S_OK;
  2115.     D3DSURFACE_DESC desc;
  2116.     float tU, tV;
  2117.  
  2118.     // Validate arguments
  2119.     if( pTexSrc == NULL || pTexDest == NULL || pCoords == NULL )
  2120.         return E_INVALIDARG;
  2121.  
  2122.     // Start with a default mapping of the complete source surface to complete 
  2123.     // destination surface
  2124.     pCoords->fLeftU = 0.0f;
  2125.     pCoords->fTopV = 0.0f;
  2126.     pCoords->fRightU = 1.0f; 
  2127.     pCoords->fBottomV = 1.0f;
  2128.  
  2129.     // If not using the complete source surface, adjust the coordinates
  2130.     if( pRectSrc != NULL )
  2131.     {
  2132.         // Get destination texture description
  2133.         hr = pTexSrc->GetLevelDesc( 0, &desc );
  2134.         if( FAILED(hr) )
  2135.             return hr;
  2136.  
  2137.         // These delta values are the distance between source texel centers in 
  2138.         // texture address space
  2139.         tU = 1.0f / desc.Width;
  2140.         tV = 1.0f / desc.Height;
  2141.  
  2142.         pCoords->fLeftU += pRectSrc->left * tU;
  2143.         pCoords->fTopV += pRectSrc->top * tV;
  2144.         pCoords->fRightU -= (desc.Width - pRectSrc->right) * tU;
  2145.         pCoords->fBottomV -= (desc.Height - pRectSrc->bottom) * tV;
  2146.     }
  2147.  
  2148.     // If not drawing to the complete destination surface, adjust the coordinates
  2149.     if( pRectDest != NULL )
  2150.     {
  2151.         // Get source texture description
  2152.         hr = pTexDest->GetLevelDesc( 0, &desc );
  2153.         if( FAILED(hr) )
  2154.             return hr;
  2155.  
  2156.         // These delta values are the distance between source texel centers in 
  2157.         // texture address space
  2158.         tU = 1.0f / desc.Width;
  2159.         tV = 1.0f / desc.Height;
  2160.  
  2161.         pCoords->fLeftU -= pRectDest->left * tU;
  2162.         pCoords->fTopV -= pRectDest->top * tV;
  2163.         pCoords->fRightU += (desc.Width - pRectDest->right) * tU;
  2164.         pCoords->fBottomV += (desc.Height - pRectDest->bottom) * tV;
  2165.     }
  2166.  
  2167.     return S_OK;
  2168. }
  2169.   
  2170.  
  2171.  
  2172.  
  2173. //-----------------------------------------------------------------------------
  2174. // Name: Scene_To_SceneScaled()
  2175. // Desc: Scale down g_pTexScene by 1/4 x 1/4 and place the result in 
  2176. //       g_pTexSceneScaled
  2177. //-----------------------------------------------------------------------------
  2178. HRESULT Scene_To_SceneScaled()
  2179. {
  2180.     HRESULT hr = S_OK;
  2181.     D3DXVECTOR2 avSampleOffsets[MAX_SAMPLES];
  2182.     
  2183.    
  2184.     // Get the new render target surface
  2185.     PDIRECT3DSURFACE9 pSurfScaledScene = NULL;
  2186.     hr = g_pTexSceneScaled->GetSurfaceLevel( 0, &pSurfScaledScene );
  2187.     if( FAILED(hr) )
  2188.         goto LCleanReturn;
  2189.  
  2190.     const D3DSURFACE_DESC* pBackBufferDesc = DXUTGetBackBufferSurfaceDesc();
  2191.  
  2192.     // Create a 1/4 x 1/4 scale copy of the HDR texture. Since bloom textures
  2193.     // are 1/8 x 1/8 scale, border texels of the HDR texture will be discarded 
  2194.     // to keep the dimensions evenly divisible by 8; this allows for precise 
  2195.     // control over sampling inside pixel shaders.
  2196.     g_pEffect->SetTechnique("DownScale4x4");
  2197.  
  2198.     // Place the rectangle in the center of the back buffer surface
  2199.     RECT rectSrc;
  2200.     rectSrc.left = (pBackBufferDesc->Width - g_dwCropWidth) / 2;
  2201.     rectSrc.top = (pBackBufferDesc->Height - g_dwCropHeight) / 2;
  2202.     rectSrc.right = rectSrc.left + g_dwCropWidth;
  2203.     rectSrc.bottom = rectSrc.top + g_dwCropHeight;
  2204.  
  2205.     // Get the texture coordinates for the render target
  2206.     CoordRect coords;
  2207.     GetTextureCoords( g_pTexScene, &rectSrc, g_pTexSceneScaled, NULL, &coords );
  2208.  
  2209.     // Get the sample offsets used within the pixel shader
  2210.     GetSampleOffsets_DownScale4x4( pBackBufferDesc->Width, pBackBufferDesc->Height, avSampleOffsets );
  2211.     g_pEffect->SetValue("g_avSampleOffsets", avSampleOffsets, sizeof(avSampleOffsets));
  2212.     
  2213.     g_pd3dDevice->SetRenderTarget( 0, pSurfScaledScene );
  2214.     g_pd3dDevice->SetTexture( 0, g_pTexScene );
  2215.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT );
  2216.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP );
  2217.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP );
  2218.    
  2219.     UINT uiPassCount, uiPass;       
  2220.     hr = g_pEffect->Begin(&uiPassCount, 0);
  2221.     if( FAILED(hr) )
  2222.         goto LCleanReturn;
  2223.  
  2224.     for (uiPass = 0; uiPass < uiPassCount; uiPass++)
  2225.     {
  2226.         g_pEffect->BeginPass(uiPass);
  2227.  
  2228.         // Draw a fullscreen quad
  2229.         DrawFullScreenQuad( coords );
  2230.  
  2231.         g_pEffect->EndPass();
  2232.     }
  2233.  
  2234.     g_pEffect->End();
  2235.     
  2236.  
  2237.     hr = S_OK;
  2238. LCleanReturn:
  2239.     SAFE_RELEASE( pSurfScaledScene );
  2240.     return hr;
  2241. }
  2242.  
  2243.  
  2244.  
  2245.  
  2246. //-----------------------------------------------------------------------------
  2247. // Name: SceneScaled_To_BrightPass
  2248. // Desc: Run the bright-pass filter on g_pTexSceneScaled and place the result
  2249. //       in g_pTexBrightPass
  2250. //-----------------------------------------------------------------------------
  2251. HRESULT SceneScaled_To_BrightPass()
  2252. {
  2253.     HRESULT hr = S_OK;
  2254.  
  2255.     D3DXVECTOR2 avSampleOffsets[MAX_SAMPLES];
  2256.     D3DXVECTOR4 avSampleWeights[MAX_SAMPLES];
  2257.  
  2258.     
  2259.     // Get the new render target surface
  2260.     PDIRECT3DSURFACE9 pSurfBrightPass;
  2261.     hr = g_pTexBrightPass->GetSurfaceLevel( 0, &pSurfBrightPass );
  2262.     if( FAILED(hr) )
  2263.         goto LCleanReturn;
  2264.  
  2265.     
  2266.     D3DSURFACE_DESC desc;
  2267.     g_pTexSceneScaled->GetLevelDesc( 0, &desc );
  2268.  
  2269.     // Get the offsets to be used within the GaussBlur5x5 pixel shader
  2270.     hr = GetSampleOffsets_GaussBlur5x5( desc.Width, desc.Height, avSampleOffsets, avSampleWeights );
  2271.     g_pEffect->SetValue("g_avSampleOffsets", avSampleOffsets, sizeof(avSampleOffsets) );
  2272.     g_pEffect->SetValue("g_avSampleWeights", avSampleWeights, sizeof(avSampleWeights) );
  2273.     
  2274.  
  2275.     // Get the rectangle describing the sampled portion of the source texture.
  2276.     // Decrease the rectangle to adjust for the single pixel black border.
  2277.     RECT rectSrc;
  2278.     GetTextureRect( g_pTexSceneScaled, &rectSrc );
  2279.     InflateRect( &rectSrc, -1, -1 );
  2280.  
  2281.     // Get the destination rectangle.
  2282.     // Decrease the rectangle to adjust for the single pixel black border.
  2283.     RECT rectDest;
  2284.     GetTextureRect( g_pTexBrightPass, &rectDest );
  2285.     InflateRect( &rectDest, -1, -1 );
  2286.  
  2287.     // Get the correct texture coordinates to apply to the rendered quad in order 
  2288.     // to sample from the source rectangle and render into the destination rectangle
  2289.     CoordRect coords;
  2290.     GetTextureCoords( g_pTexSceneScaled, &rectSrc, g_pTexBrightPass, &rectDest, &coords );
  2291.  
  2292.     // The bright-pass filter removes everything from the scene except lights and
  2293.     // bright reflections
  2294.     g_pEffect->SetTechnique("BrightPassFilter");
  2295.  
  2296.     g_pd3dDevice->SetRenderTarget( 0, pSurfBrightPass );
  2297.     g_pd3dDevice->SetTexture( 0, g_pTexSceneScaled );
  2298.     g_pd3dDevice->SetTexture( 1, g_pTexAdaptedLuminanceCur );
  2299.     g_pd3dDevice->SetRenderState( D3DRS_SCISSORTESTENABLE, TRUE );
  2300.     g_pd3dDevice->SetScissorRect( &rectDest );
  2301.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT );
  2302.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
  2303.     g_pd3dDevice->SetSamplerState( 1, D3DSAMP_MINFILTER, D3DTEXF_POINT );
  2304.     g_pd3dDevice->SetSamplerState( 1, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
  2305.        
  2306.     UINT uiPass, uiPassCount;
  2307.     hr = g_pEffect->Begin(&uiPassCount, 0);
  2308.     if( FAILED(hr) )
  2309.         goto LCleanReturn;
  2310.     
  2311.     for (uiPass = 0; uiPass < uiPassCount; uiPass++)
  2312.     {
  2313.         g_pEffect->BeginPass(uiPass);
  2314.  
  2315.         // Draw a fullscreen quad to sample the RT
  2316.         DrawFullScreenQuad( coords );
  2317.  
  2318.         g_pEffect->EndPass();
  2319.     }
  2320.     
  2321.     g_pEffect->End();
  2322.     g_pd3dDevice->SetRenderState( D3DRS_SCISSORTESTENABLE, FALSE );
  2323.  
  2324.     hr = S_OK;
  2325. LCleanReturn:
  2326.     SAFE_RELEASE( pSurfBrightPass );
  2327.     return hr;
  2328. }
  2329.  
  2330.  
  2331.  
  2332.  
  2333. //-----------------------------------------------------------------------------
  2334. // Name: BrightPass_To_StarSource
  2335. // Desc: Perform a 5x5 gaussian blur on g_pTexBrightPass and place the result
  2336. //       in g_pTexStarSource. The bright-pass filtered image is blurred before
  2337. //       being used for star operations to avoid aliasing artifacts.
  2338. //-----------------------------------------------------------------------------
  2339. HRESULT BrightPass_To_StarSource()
  2340. {
  2341.     HRESULT hr = S_OK;
  2342.  
  2343.     D3DXVECTOR2 avSampleOffsets[MAX_SAMPLES];
  2344.     D3DXVECTOR4 avSampleWeights[MAX_SAMPLES];
  2345.  
  2346.     // Get the new render target surface
  2347.     PDIRECT3DSURFACE9 pSurfStarSource;
  2348.     hr = g_pTexStarSource->GetSurfaceLevel( 0, &pSurfStarSource );
  2349.     if( FAILED(hr) )
  2350.         goto LCleanReturn;
  2351.  
  2352.     
  2353.     // Get the destination rectangle.
  2354.     // Decrease the rectangle to adjust for the single pixel black border.
  2355.     RECT rectDest;
  2356.     GetTextureRect( g_pTexStarSource, &rectDest );
  2357.     InflateRect( &rectDest, -1, -1 );
  2358.  
  2359.     // Get the correct texture coordinates to apply to the rendered quad in order 
  2360.     // to sample from the source rectangle and render into the destination rectangle
  2361.     CoordRect coords;
  2362.     GetTextureCoords( g_pTexBrightPass, NULL, g_pTexStarSource, &rectDest, &coords );
  2363.  
  2364.     // Get the sample offsets used within the pixel shader
  2365.     D3DSURFACE_DESC desc;
  2366.     hr = g_pTexBrightPass->GetLevelDesc( 0, &desc );
  2367.     if( FAILED(hr) )
  2368.         return hr;
  2369.  
  2370.     
  2371.     GetSampleOffsets_GaussBlur5x5( desc.Width, desc.Height, avSampleOffsets, avSampleWeights );
  2372.     g_pEffect->SetValue("g_avSampleOffsets", avSampleOffsets, sizeof(avSampleOffsets));
  2373.     g_pEffect->SetValue("g_avSampleWeights", avSampleWeights, sizeof(avSampleWeights));
  2374.     
  2375.     // The gaussian blur smooths out rough edges to avoid aliasing effects
  2376.     // when the star effect is run
  2377.     g_pEffect->SetTechnique("GaussBlur5x5");
  2378.  
  2379.     g_pd3dDevice->SetRenderTarget( 0, pSurfStarSource );
  2380.     g_pd3dDevice->SetTexture( 0, g_pTexBrightPass );
  2381.     g_pd3dDevice->SetScissorRect( &rectDest );
  2382.     g_pd3dDevice->SetRenderState( D3DRS_SCISSORTESTENABLE, TRUE );
  2383.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT );
  2384.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP );
  2385.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP );
  2386.    
  2387.     UINT uiPassCount, uiPass;       
  2388.     hr = g_pEffect->Begin(&uiPassCount, 0);
  2389.     if( FAILED(hr) )
  2390.         goto LCleanReturn;
  2391.  
  2392.     for (uiPass = 0; uiPass < uiPassCount; uiPass++)
  2393.     {
  2394.         g_pEffect->BeginPass(uiPass);
  2395.  
  2396.         // Draw a fullscreen quad
  2397.         DrawFullScreenQuad( coords );
  2398.  
  2399.         g_pEffect->EndPass();
  2400.     }
  2401.  
  2402.     g_pEffect->End();
  2403.     g_pd3dDevice->SetRenderState( D3DRS_SCISSORTESTENABLE, FALSE );
  2404.  
  2405.   
  2406.     hr = S_OK;
  2407. LCleanReturn:
  2408.     SAFE_RELEASE( pSurfStarSource);
  2409.     return hr;
  2410. }
  2411.  
  2412.  
  2413.  
  2414.  
  2415. //-----------------------------------------------------------------------------
  2416. // Name: StarSource_To_BloomSource
  2417. // Desc: Scale down g_pTexStarSource by 1/2 x 1/2 and place the result in 
  2418. //       g_pTexBloomSource
  2419. //-----------------------------------------------------------------------------
  2420. HRESULT StarSource_To_BloomSource()
  2421. {
  2422.     HRESULT hr = S_OK;
  2423.  
  2424.     D3DXVECTOR2 avSampleOffsets[MAX_SAMPLES];
  2425.     
  2426.     // Get the new render target surface
  2427.     PDIRECT3DSURFACE9 pSurfBloomSource;
  2428.     hr = g_pTexBloomSource->GetSurfaceLevel( 0, &pSurfBloomSource );
  2429.     if( FAILED(hr) )
  2430.         goto LCleanReturn;
  2431.  
  2432.     
  2433.     // Get the rectangle describing the sampled portion of the source texture.
  2434.     // Decrease the rectangle to adjust for the single pixel black border.
  2435.     RECT rectSrc;
  2436.     GetTextureRect( g_pTexStarSource, &rectSrc );
  2437.     InflateRect( &rectSrc, -1, -1 );
  2438.  
  2439.     // Get the destination rectangle.
  2440.     // Decrease the rectangle to adjust for the single pixel black border.
  2441.     RECT rectDest;
  2442.     GetTextureRect( g_pTexBloomSource, &rectDest );
  2443.     InflateRect( &rectDest, -1, -1 );
  2444.  
  2445.     // Get the correct texture coordinates to apply to the rendered quad in order 
  2446.     // to sample from the source rectangle and render into the destination rectangle
  2447.     CoordRect coords;
  2448.     GetTextureCoords( g_pTexStarSource, &rectSrc, g_pTexBloomSource, &rectDest, &coords );
  2449.  
  2450.     // Get the sample offsets used within the pixel shader
  2451.     D3DSURFACE_DESC desc;
  2452.     hr = g_pTexBrightPass->GetLevelDesc( 0, &desc );
  2453.     if( FAILED(hr) )
  2454.         return hr;
  2455.  
  2456.     GetSampleOffsets_DownScale2x2( desc.Width, desc.Height, avSampleOffsets );
  2457.     g_pEffect->SetValue("g_avSampleOffsets", avSampleOffsets, sizeof(avSampleOffsets));
  2458.  
  2459.     // Create an exact 1/2 x 1/2 copy of the source texture
  2460.     g_pEffect->SetTechnique("DownScale2x2");
  2461.  
  2462.     g_pd3dDevice->SetRenderTarget( 0, pSurfBloomSource );
  2463.     g_pd3dDevice->SetTexture( 0, g_pTexStarSource );
  2464.     g_pd3dDevice->SetScissorRect( &rectDest );
  2465.     g_pd3dDevice->SetRenderState( D3DRS_SCISSORTESTENABLE, TRUE );
  2466.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT );
  2467.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP );
  2468.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP );
  2469.    
  2470.     UINT uiPassCount, uiPass;       
  2471.     hr = g_pEffect->Begin(&uiPassCount, 0);
  2472.     if( FAILED(hr) )
  2473.         goto LCleanReturn;
  2474.  
  2475.     for (uiPass = 0; uiPass < uiPassCount; uiPass++)
  2476.     {
  2477.         g_pEffect->BeginPass(uiPass);
  2478.  
  2479.         // Draw a fullscreen quad
  2480.         DrawFullScreenQuad( coords );
  2481.  
  2482.         g_pEffect->EndPass();
  2483.     }
  2484.  
  2485.     g_pEffect->End();
  2486.     g_pd3dDevice->SetRenderState( D3DRS_SCISSORTESTENABLE, FALSE );
  2487.  
  2488.  
  2489.     
  2490.     hr = S_OK;
  2491. LCleanReturn:
  2492.     SAFE_RELEASE( pSurfBloomSource);
  2493.     return hr;
  2494. }
  2495.  
  2496.  
  2497.  
  2498.  
  2499. //-----------------------------------------------------------------------------
  2500. // Name: GetSampleOffsets_DownScale4x4
  2501. // Desc: Get the texture coordinate offsets to be used inside the DownScale4x4
  2502. //       pixel shader.
  2503. //-----------------------------------------------------------------------------
  2504. HRESULT GetSampleOffsets_DownScale4x4( DWORD dwWidth, DWORD dwHeight, D3DXVECTOR2 avSampleOffsets[] )
  2505. {
  2506.     if( NULL == avSampleOffsets )
  2507.         return E_INVALIDARG;
  2508.  
  2509.     float tU = 1.0f / dwWidth;
  2510.     float tV = 1.0f / dwHeight;
  2511.  
  2512.     // Sample from the 16 surrounding points. Since the center point will be in
  2513.     // the exact center of 16 texels, a 0.5f offset is needed to specify a texel
  2514.     // center.
  2515.     int index=0;
  2516.     for( int y=0; y < 4; y++ )
  2517.     {
  2518.         for( int x=0; x < 4; x++ )
  2519.         {
  2520.             avSampleOffsets[ index ].x = (x - 1.5f) * tU;
  2521.             avSampleOffsets[ index ].y = (y - 1.5f) * tV;
  2522.                                                       
  2523.             index++;
  2524.         }
  2525.     }
  2526.  
  2527.     return S_OK;
  2528. }
  2529.  
  2530.  
  2531.  
  2532.  
  2533. //-----------------------------------------------------------------------------
  2534. // Name: GetSampleOffsets_DownScale2x2
  2535. // Desc: Get the texture coordinate offsets to be used inside the DownScale2x2
  2536. //       pixel shader.
  2537. //-----------------------------------------------------------------------------
  2538. HRESULT GetSampleOffsets_DownScale2x2( DWORD dwWidth, DWORD dwHeight, D3DXVECTOR2 avSampleOffsets[] )
  2539. {
  2540.     if( NULL == avSampleOffsets )
  2541.         return E_INVALIDARG;
  2542.  
  2543.     float tU = 1.0f / dwWidth;
  2544.     float tV = 1.0f / dwHeight;
  2545.  
  2546.     // Sample from the 4 surrounding points. Since the center point will be in
  2547.     // the exact center of 4 texels, a 0.5f offset is needed to specify a texel
  2548.     // center.
  2549.     int index=0;
  2550.     for( int y=0; y < 2; y++ )
  2551.     {
  2552.         for( int x=0; x < 2; x++ )
  2553.         {
  2554.             avSampleOffsets[ index ].x = (x - 0.5f) * tU;
  2555.             avSampleOffsets[ index ].y = (y - 0.5f) * tV;
  2556.                                                       
  2557.             index++;
  2558.         }
  2559.     }
  2560.  
  2561.     return S_OK;
  2562. }
  2563.  
  2564.  
  2565.  
  2566.  
  2567. //-----------------------------------------------------------------------------
  2568. // Name: GetSampleOffsets_GaussBlur5x5
  2569. // Desc: Get the texture coordinate offsets to be used inside the GaussBlur5x5
  2570. //       pixel shader.
  2571. //-----------------------------------------------------------------------------
  2572. HRESULT GetSampleOffsets_GaussBlur5x5(DWORD dwD3DTexWidth,
  2573.                                                          DWORD dwD3DTexHeight,
  2574.                                                          D3DXVECTOR2* avTexCoordOffset,
  2575.                                                          D3DXVECTOR4* avSampleWeight,
  2576.                                                          FLOAT fMultiplier )
  2577. {
  2578.     float tu = 1.0f / (float)dwD3DTexWidth ;
  2579.     float tv = 1.0f / (float)dwD3DTexHeight ;
  2580.  
  2581.     D3DXVECTOR4 vWhite( 1.0f, 1.0f, 1.0f, 1.0f );
  2582.     
  2583.     float totalWeight = 0.0f;
  2584.     int index=0;
  2585.     for( int x = -2; x <= 2; x++ )
  2586.     {
  2587.         for( int y = -2; y <= 2; y++ )
  2588.         {
  2589.             // Exclude pixels with a block distance greater than 2. This will
  2590.             // create a kernel which approximates a 5x5 kernel using only 13
  2591.             // sample points instead of 25; this is necessary since 2.0 shaders
  2592.             // only support 16 texture grabs.
  2593.             if( abs(x) + abs(y) > 2 )
  2594.                 continue;
  2595.  
  2596.             // Get the unscaled Gaussian intensity for this offset
  2597.             avTexCoordOffset[index] = D3DXVECTOR2( x * tu, y * tv );
  2598.             avSampleWeight[index] = vWhite * GaussianDistribution( (float)x, (float)y, 1.0f );
  2599.             totalWeight += avSampleWeight[index].x;
  2600.  
  2601.             index++;
  2602.         }
  2603.     }
  2604.  
  2605.     // Divide the current weight by the total weight of all the samples; Gaussian
  2606.     // blur kernels add to 1.0f to ensure that the intensity of the image isn't
  2607.     // changed when the blur occurs. An optional multiplier variable is used to
  2608.     // add or remove image intensity during the blur.
  2609.     for( int i=0; i < index; i++ )
  2610.     {
  2611.         avSampleWeight[i] /= totalWeight;
  2612.         avSampleWeight[i] *= fMultiplier;
  2613.     }
  2614.  
  2615.     return S_OK;
  2616. }
  2617.  
  2618.  
  2619.  
  2620.  
  2621. //-----------------------------------------------------------------------------
  2622. // Name: GetSampleOffsets_Bloom
  2623. // Desc: Get the texture coordinate offsets to be used inside the Bloom
  2624. //       pixel shader.
  2625. //-----------------------------------------------------------------------------
  2626. HRESULT GetSampleOffsets_Bloom( DWORD dwD3DTexSize,
  2627.                                                    float afTexCoordOffset[15],
  2628.                                                    D3DXVECTOR4* avColorWeight,
  2629.                                                    float fDeviation,
  2630.                                                    float fMultiplier )
  2631. {
  2632.     int i=0;
  2633.     float tu = 1.0f / (float)dwD3DTexSize;
  2634.  
  2635.     // Fill the center texel
  2636.     float weight = fMultiplier * GaussianDistribution( 0, 0, fDeviation );
  2637.     avColorWeight[0] = D3DXVECTOR4( weight, weight, weight, 1.0f );
  2638.  
  2639.     afTexCoordOffset[0] = 0.0f;
  2640.     
  2641.     // Fill the first half
  2642.     for( i=1; i < 8; i++ )
  2643.     {
  2644.         // Get the Gaussian intensity for this offset
  2645.         weight = fMultiplier * GaussianDistribution( (float)i, 0, fDeviation );
  2646.         afTexCoordOffset[i] = i * tu;
  2647.  
  2648.         avColorWeight[i] = D3DXVECTOR4( weight, weight, weight, 1.0f );
  2649.     }
  2650.  
  2651.     // Mirror to the second half
  2652.     for( i=8; i < 15; i++ )
  2653.     {
  2654.         avColorWeight[i] = avColorWeight[i-7];
  2655.         afTexCoordOffset[i] = -afTexCoordOffset[i-7];
  2656.     }
  2657.  
  2658.     return S_OK;
  2659. }
  2660.  
  2661.  
  2662.  
  2663.  
  2664. //-----------------------------------------------------------------------------
  2665. // Name: GetSampleOffsets_Bloom
  2666. // Desc: Get the texture coordinate offsets to be used inside the Bloom
  2667. //       pixel shader.
  2668. //-----------------------------------------------------------------------------
  2669. HRESULT GetSampleOffsets_Star(DWORD dwD3DTexSize,
  2670.                                                 float afTexCoordOffset[15],
  2671.                                                 D3DXVECTOR4* avColorWeight,
  2672.                                                 float fDeviation)
  2673. {
  2674.     int i=0;
  2675.     float tu = 1.0f / (float)dwD3DTexSize;
  2676.  
  2677.     // Fill the center texel
  2678.     float weight = 1.0f * GaussianDistribution( 0, 0, fDeviation );
  2679.     avColorWeight[0] = D3DXVECTOR4( weight, weight, weight, 1.0f );
  2680.  
  2681.     afTexCoordOffset[0] = 0.0f;
  2682.     
  2683.     // Fill the first half
  2684.     for( i=1; i < 8; i++ )
  2685.     {
  2686.         // Get the Gaussian intensity for this offset
  2687.         weight = 1.0f * GaussianDistribution( (float)i, 0, fDeviation );
  2688.         afTexCoordOffset[i] = i * tu;
  2689.  
  2690.         avColorWeight[i] = D3DXVECTOR4( weight, weight, weight, 1.0f );
  2691.     }
  2692.  
  2693.     // Mirror to the second half
  2694.     for( i=8; i < 15; i++ )
  2695.     {
  2696.         avColorWeight[i] = avColorWeight[i-7];
  2697.         afTexCoordOffset[i] = -afTexCoordOffset[i-7];
  2698.     }
  2699.  
  2700.     return S_OK;
  2701. }
  2702.  
  2703.  
  2704.  
  2705.  
  2706. //-----------------------------------------------------------------------------
  2707. // Name: GaussianDistribution
  2708. // Desc: Helper function for GetSampleOffsets function to compute the 
  2709. //       2 parameter Gaussian distrubution using the given standard deviation
  2710. //       rho
  2711. //-----------------------------------------------------------------------------
  2712. float GaussianDistribution( float x, float y, float rho )
  2713. {
  2714.     float g = 1.0f / sqrtf( 2.0f * D3DX_PI * rho * rho );
  2715.     g *= expf( -(x*x + y*y)/(2*rho*rho) );
  2716.  
  2717.     return g;
  2718. }
  2719.  
  2720.  
  2721. //--------------------------------------------------------------------------------------
  2722. // Render the help and statistics text. This function uses the ID3DXFont interface for 
  2723. // efficient text rendering.
  2724. //--------------------------------------------------------------------------------------
  2725. void RenderText()
  2726. {
  2727.     // The helper object simply helps keep track of text position, and color
  2728.     // and then it calls pFont->DrawText( g_pSprite, strMsg, -1, &rc, DT_NOCLIP, g_clr );
  2729.     // If NULL is passed in as the sprite object, then it will work however the 
  2730.     // pFont->DrawText() will not be batched together.  Batching calls will improves performance.
  2731.     CDXUTTextHelper txtHelper( g_pFont, g_pTextSprite, 15 );
  2732.  
  2733.     // Output statistics
  2734.     txtHelper.Begin();
  2735.     txtHelper.SetInsertionPos( 5, 5 );
  2736.     txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) );
  2737.     txtHelper.DrawTextLine( DXUTGetFrameStats() );
  2738.     txtHelper.DrawTextLine( DXUTGetDeviceStats() );
  2739.  
  2740.     txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
  2741.     txtHelper.DrawFormattedTextLine( L"Glare type: %s", g_GlareDef.m_strGlareName );
  2742.     
  2743.     // Draw help
  2744.     if( g_bShowHelp )
  2745.     {
  2746.         const D3DSURFACE_DESC* pd3dsdBackBuffer = DXUTGetBackBufferSurfaceDesc();
  2747.         txtHelper.SetInsertionPos( 10, pd3dsdBackBuffer->Height-15*6 );
  2748.         txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 0.75f, 0.0f, 1.0f ) );
  2749.         txtHelper.DrawTextLine( L"Controls (F1 to hide):" );
  2750.  
  2751.         txtHelper.SetInsertionPos( 40, pd3dsdBackBuffer->Height-15*5 );
  2752.         txtHelper.DrawTextLine( L"Look: Left drag mouse\n"
  2753.                                 L"Move: A,W,S,D or Arrow Keys\n"
  2754.                                 L"Quit: ESC" );
  2755.     }
  2756.     else
  2757.     {
  2758.         txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
  2759.         txtHelper.DrawTextLine( L"Press F1 for help" );
  2760.     }
  2761.     txtHelper.End();
  2762. }
  2763.  
  2764.  
  2765. //--------------------------------------------------------------------------------------
  2766. // Before handling window messages, the sample framework passes incoming windows 
  2767. // messages to the application through this callback function. If the application sets 
  2768. // *pbNoFurtherProcessing to TRUE, then the sample framework will not process this message.
  2769. //--------------------------------------------------------------------------------------
  2770. LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing )
  2771. {
  2772.     // Give the dialogs a chance to handle the message first
  2773.     *pbNoFurtherProcessing = g_HUD.MsgProc( hWnd, uMsg, wParam, lParam );
  2774.     if( *pbNoFurtherProcessing )
  2775.         return 0;
  2776.     *pbNoFurtherProcessing = g_SampleUI.MsgProc( hWnd, uMsg, wParam, lParam );
  2777.     if( *pbNoFurtherProcessing )
  2778.         return 0;
  2779.  
  2780.     // Pass all remaining windows messages to camera so it can respond to user input
  2781.     g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam );
  2782.  
  2783.     return 0;
  2784. }
  2785.  
  2786.  
  2787. //--------------------------------------------------------------------------------------
  2788. // As a convenience, the sample framework inspects the incoming windows messages for
  2789. // keystroke messages and decodes the message parameters to pass relevant keyboard
  2790. // messages to the application.  The framework does not remove the underlying keystroke 
  2791. // messages, which are still passed to the application's MsgProc callback.
  2792. //--------------------------------------------------------------------------------------
  2793. void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown )
  2794. {
  2795.     if( bKeyDown )
  2796.     {
  2797.         switch( nChar )
  2798.         {
  2799.             case VK_F1: g_bShowHelp = !g_bShowHelp; break;
  2800.         }
  2801.     }
  2802. }
  2803.  
  2804.  
  2805. //--------------------------------------------------------------------------------------
  2806. // Handles the GUI events
  2807. //--------------------------------------------------------------------------------------
  2808. void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl )
  2809. {
  2810.     CDXUTStatic* pStatic = NULL;
  2811.     CDXUTComboBox* pComboBox = NULL;
  2812.     CDXUTSlider* pSlider = NULL;
  2813.     CDXUTCheckBox* pCheckBox = NULL;
  2814.     WCHAR strBuffer[256] = {0};
  2815.  
  2816.     switch( nControlID )
  2817.     {
  2818.         case IDC_TOGGLEFULLSCREEN: DXUTToggleFullScreen(); break;
  2819.         case IDC_TOGGLEREF:        DXUTToggleREF(); break;
  2820.         case IDC_CHANGEDEVICE:     DXUTSetShowSettingsDialog( !DXUTGetShowSettingsDialog() ); break;
  2821.         case IDC_RESET:            ResetOptions(); break;
  2822.         
  2823.         case IDC_TONEMAP:          
  2824.             pCheckBox = (CDXUTCheckBox*) pControl;
  2825.             g_bToneMap = pCheckBox->GetChecked();
  2826.             break;
  2827.  
  2828.         case IDC_BLUESHIFT:          
  2829.             pCheckBox = (CDXUTCheckBox*) pControl;
  2830.             g_bBlueShift = pCheckBox->GetChecked();
  2831.             break;
  2832.  
  2833.         case IDC_GLARETYPE:
  2834.             pComboBox = (CDXUTComboBox*) pControl;
  2835.             g_eGlareType = (EGLARELIBTYPE)(INT_PTR) pComboBox->GetSelectedData();
  2836.             g_GlareDef.Initialize( g_eGlareType );
  2837.             break;
  2838.  
  2839.         case IDC_KEYVALUE:
  2840.             pSlider = (CDXUTSlider*) pControl;
  2841.             g_fKeyValue = pSlider->GetValue() / 100.0f;
  2842.  
  2843.             _snwprintf( strBuffer, 255, L"Key Value: %.2f", g_fKeyValue );
  2844.             pStatic = g_SampleUI.GetStatic( IDC_KEYVALUE_LABEL );
  2845.             pStatic->SetText( strBuffer );
  2846.             break;
  2847.  
  2848.         case IDC_LIGHT0:
  2849.         case IDC_LIGHT1:
  2850.         {
  2851.             int iLight = 0;
  2852.  
  2853.             if( nControlID == IDC_LIGHT0 )
  2854.             {
  2855.                 iLight = 0;
  2856.                 pStatic = g_SampleUI.GetStatic( IDC_LIGHT0_LABEL );
  2857.             }
  2858.             else if( nControlID == IDC_LIGHT1 )
  2859.             {
  2860.                 iLight = 1;
  2861.                 pStatic = g_SampleUI.GetStatic( IDC_LIGHT1_LABEL );
  2862.             }
  2863.             
  2864.             pSlider = (CDXUTSlider*) pControl;
  2865.             g_nLightMantissa[iLight] = 1 + (pSlider->GetValue()) % 9;
  2866.             g_nLightLogIntensity[iLight] = -4 + ( pSlider->GetValue() ) / 9;
  2867.             RefreshLights();
  2868.             
  2869.             break;
  2870.         }
  2871.  
  2872.         
  2873.     }
  2874. }
  2875.  
  2876.  
  2877. //--------------------------------------------------------------------------------------
  2878. // This callback function will be called immediately after the Direct3D device has 
  2879. // entered a lost state and before IDirect3DDevice9::Reset is called. Resources created
  2880. // in the OnResetDevice callback should be released here, which generally includes all 
  2881. // D3DPOOL_DEFAULT resources. See the "Lost Devices" section of the documentation for 
  2882. // information about lost devices.
  2883. //--------------------------------------------------------------------------------------
  2884. void CALLBACK OnLostDevice()
  2885. {
  2886.     int i=0;
  2887.  
  2888.     if( g_pFont )
  2889.         g_pFont->OnLostDevice();
  2890.     if( g_pEffect )
  2891.         g_pEffect->OnLostDevice();
  2892.  
  2893.  
  2894.     SAFE_RELEASE(g_pTextSprite);
  2895.     
  2896.     SAFE_RELEASE(g_pWorldMesh);
  2897.     SAFE_RELEASE(g_pmeshSphere);
  2898.  
  2899.     SAFE_RELEASE(g_pTexScene);
  2900.     SAFE_RELEASE(g_pTexSceneScaled);
  2901.     SAFE_RELEASE(g_pTexWall);
  2902.     SAFE_RELEASE(g_pTexFloor);
  2903.     SAFE_RELEASE(g_pTexCeiling);
  2904.     SAFE_RELEASE(g_pTexPainting);
  2905.     SAFE_RELEASE(g_pTexAdaptedLuminanceCur);
  2906.     SAFE_RELEASE(g_pTexAdaptedLuminanceLast);
  2907.     SAFE_RELEASE(g_pTexBrightPass);
  2908.     SAFE_RELEASE(g_pTexBloomSource);
  2909.     SAFE_RELEASE(g_pTexStarSource);
  2910.     
  2911.     for( i=0; i < NUM_TONEMAP_TEXTURES; i++)
  2912.     {
  2913.         SAFE_RELEASE(g_apTexToneMap[i]);
  2914.     }
  2915.  
  2916.     for( i=0; i < NUM_STAR_TEXTURES; i++ )
  2917.     {
  2918.         SAFE_RELEASE(g_apTexStar[i]);
  2919.     }
  2920.  
  2921.     for( i=0; i < NUM_BLOOM_TEXTURES; i++ )
  2922.     {
  2923.         SAFE_RELEASE(g_apTexBloom[i]);
  2924.     }
  2925. }
  2926.  
  2927.  
  2928. //--------------------------------------------------------------------------------------
  2929. // This callback function will be called immediately after the Direct3D device has 
  2930. // been destroyed, which generally happens as a result of application termination or 
  2931. // windowed/full screen toggles. Resources created in the OnCreateDevice callback 
  2932. // should be released here, which generally includes all D3DPOOL_MANAGED resources. 
  2933. //--------------------------------------------------------------------------------------
  2934. void CALLBACK OnDestroyDevice()
  2935. {
  2936.     SAFE_RELEASE(g_pEffect);
  2937.     SAFE_RELEASE(g_pFont);
  2938. }
  2939.  
  2940.  
  2941.  
  2942.